mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
rebase: vendor dependencies for Vault API
Uses github.com/libopenstorage/secrets to communicate with Vault. This removes the need for maintaining our own limited Vault APIs. By adding the new dependency, several other packages got updated in the process. Unused indirect dependencies have been removed from go.mod. Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
committed by
mergify[bot]
parent
7824cb5ed7
commit
91774fc936
363
vendor/github.com/hashicorp/vault/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/vault/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. "Contributor"
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the terms of
|
||||
a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
|
||||
means a work that combines Covered Software with other material, in a
|
||||
separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether
|
||||
at the time of the initial grant or subsequently, any and all of the
|
||||
rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the License,
|
||||
by the making, using, selling, offering for sale, having made, import,
|
||||
or transfer of either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, "control" means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights to
|
||||
grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter the
|
||||
recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||
limitations of liability) contained within the Source Code Form of the
|
||||
Covered Software, except that You may alter any license notices to the
|
||||
extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute,
|
||||
judicial order, or regulation then You must: (a) comply with the terms of
|
||||
this License to the maximum extent possible; and (b) describe the
|
||||
limitations and the code they affect. Such description must be placed in a
|
||||
text file included with all distributions of the Covered Software under
|
||||
this License. Except to the extent prohibited by statute or regulation,
|
||||
such description must be sufficiently detailed for a recipient of ordinary
|
||||
skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||
basis, if such Contributor fails to notify You of the non-compliance by
|
||||
some reasonable means prior to 60 days after You have come back into
|
||||
compliance. Moreover, Your grants from a particular Contributor are
|
||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||
non-compliance by some reasonable means, this is the first time You have
|
||||
received notice of non-compliance with this License from such
|
||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||
of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an "as is" basis,
|
||||
without warranty of any kind, either expressed, implied, or statutory,
|
||||
including, without limitation, warranties that the Covered Software is free
|
||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||
The entire risk as to the quality and performance of the Covered Software
|
||||
is with You. Should any Covered Software prove defective in any respect,
|
||||
You (not any Contributor) assume the cost of any necessary servicing,
|
||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||
part of this License. No use of any Covered Software is authorized under
|
||||
this License except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from
|
||||
such party's negligence to the extent applicable law prohibits such
|
||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||
incidental or consequential damages, so this exclusion and limitation may
|
||||
not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts
|
||||
of a jurisdiction where the defendant maintains its principal place of
|
||||
business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||
in this Section shall prevent a party's ability to bring cross-claims or
|
||||
counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides that
|
||||
the language of a contract shall be construed against the drafter shall not
|
||||
be used to construe this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses If You choose to distribute Source Code Form that is
|
||||
Incompatible With Secondary Licenses under the terms of this version of
|
||||
the License, the notice described in Exhibit B of this License must be
|
||||
attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file,
|
||||
then You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a
|
||||
notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible
|
||||
With Secondary Licenses", as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
363
vendor/github.com/hashicorp/vault/api/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/vault/api/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. "Contributor"
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the terms of
|
||||
a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
|
||||
means a work that combines Covered Software with other material, in a
|
||||
separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether
|
||||
at the time of the initial grant or subsequently, any and all of the
|
||||
rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the License,
|
||||
by the making, using, selling, offering for sale, having made, import,
|
||||
or transfer of either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, "control" means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights to
|
||||
grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter the
|
||||
recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||
limitations of liability) contained within the Source Code Form of the
|
||||
Covered Software, except that You may alter any license notices to the
|
||||
extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute,
|
||||
judicial order, or regulation then You must: (a) comply with the terms of
|
||||
this License to the maximum extent possible; and (b) describe the
|
||||
limitations and the code they affect. Such description must be placed in a
|
||||
text file included with all distributions of the Covered Software under
|
||||
this License. Except to the extent prohibited by statute or regulation,
|
||||
such description must be sufficiently detailed for a recipient of ordinary
|
||||
skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||
basis, if such Contributor fails to notify You of the non-compliance by
|
||||
some reasonable means prior to 60 days after You have come back into
|
||||
compliance. Moreover, Your grants from a particular Contributor are
|
||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||
non-compliance by some reasonable means, this is the first time You have
|
||||
received notice of non-compliance with this License from such
|
||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||
of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an "as is" basis,
|
||||
without warranty of any kind, either expressed, implied, or statutory,
|
||||
including, without limitation, warranties that the Covered Software is free
|
||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||
The entire risk as to the quality and performance of the Covered Software
|
||||
is with You. Should any Covered Software prove defective in any respect,
|
||||
You (not any Contributor) assume the cost of any necessary servicing,
|
||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||
part of this License. No use of any Covered Software is authorized under
|
||||
this License except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from
|
||||
such party's negligence to the extent applicable law prohibits such
|
||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||
incidental or consequential damages, so this exclusion and limitation may
|
||||
not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts
|
||||
of a jurisdiction where the defendant maintains its principal place of
|
||||
business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||
in this Section shall prevent a party's ability to bring cross-claims or
|
||||
counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides that
|
||||
the language of a contract shall be construed against the drafter shall not
|
||||
be used to construe this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses If You choose to distribute Source Code Form that is
|
||||
Incompatible With Secondary Licenses under the terms of this version of
|
||||
the License, the notice described in Exhibit B of this License must be
|
||||
attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file,
|
||||
then You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a
|
||||
notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible
|
||||
With Secondary Licenses", as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
11
vendor/github.com/hashicorp/vault/api/auth.go
generated
vendored
Normal file
11
vendor/github.com/hashicorp/vault/api/auth.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package api
|
||||
|
||||
// Auth is used to perform credential backend related operations.
|
||||
type Auth struct {
|
||||
c *Client
|
||||
}
|
||||
|
||||
// Auth is used to return the client for credential-backend API calls.
|
||||
func (c *Client) Auth() *Auth {
|
||||
return &Auth{c: c}
|
||||
}
|
296
vendor/github.com/hashicorp/vault/api/auth_token.go
generated
vendored
Normal file
296
vendor/github.com/hashicorp/vault/api/auth_token.go
generated
vendored
Normal file
@ -0,0 +1,296 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
// TokenAuth is used to perform token backend operations on Vault
|
||||
type TokenAuth struct {
|
||||
c *Client
|
||||
}
|
||||
|
||||
// Token is used to return the client for token-backend API calls
|
||||
func (a *Auth) Token() *TokenAuth {
|
||||
return &TokenAuth{c: a.c}
|
||||
}
|
||||
|
||||
func (c *TokenAuth) Create(opts *TokenCreateRequest) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/create")
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) CreateOrphan(opts *TokenCreateRequest) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/create-orphan")
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) CreateWithRole(opts *TokenCreateRequest, roleName string) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/create/"+roleName)
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) Lookup(token string) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/lookup")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"token": token,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) LookupAccessor(accessor string) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/lookup-accessor")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"accessor": accessor,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) LookupSelf() (*Secret, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/auth/token/lookup-self")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) RenewAccessor(accessor string, increment int) (*Secret, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/renew-accessor")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"accessor": accessor,
|
||||
"increment": increment,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) Renew(token string, increment int) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"token": token,
|
||||
"increment": increment,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *TokenAuth) RenewSelf(increment int) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew-self")
|
||||
|
||||
body := map[string]interface{}{"increment": increment}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
// RenewTokenAsSelf behaves like renew-self, but authenticates using a provided
|
||||
// token instead of the token attached to the client.
|
||||
func (c *TokenAuth) RenewTokenAsSelf(token string, increment int) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/renew-self")
|
||||
r.ClientToken = token
|
||||
|
||||
body := map[string]interface{}{"increment": increment}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
// RevokeAccessor revokes a token associated with the given accessor
|
||||
// along with all the child tokens.
|
||||
func (c *TokenAuth) RevokeAccessor(accessor string) error {
|
||||
r := c.c.NewRequest("POST", "/v1/auth/token/revoke-accessor")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"accessor": accessor,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeOrphan revokes a token without revoking the tree underneath it (so
|
||||
// child tokens are orphaned rather than revoked)
|
||||
func (c *TokenAuth) RevokeOrphan(token string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke-orphan")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"token": token,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeSelf revokes the token making the call. The `token` parameter is kept
|
||||
// for backwards compatibility but is ignored; only the client's set token has
|
||||
// an effect.
|
||||
func (c *TokenAuth) RevokeSelf(token string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke-self")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RevokeTree is the "normal" revoke operation that revokes the given token and
|
||||
// the entire tree underneath -- all of its child tokens, their child tokens,
|
||||
// etc.
|
||||
func (c *TokenAuth) RevokeTree(token string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/auth/token/revoke")
|
||||
if err := r.SetJSONBody(map[string]interface{}{
|
||||
"token": token,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TokenCreateRequest is the options structure for creating a token.
|
||||
type TokenCreateRequest struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Policies []string `json:"policies,omitempty"`
|
||||
Metadata map[string]string `json:"meta,omitempty"`
|
||||
Lease string `json:"lease,omitempty"`
|
||||
TTL string `json:"ttl,omitempty"`
|
||||
ExplicitMaxTTL string `json:"explicit_max_ttl,omitempty"`
|
||||
Period string `json:"period,omitempty"`
|
||||
NoParent bool `json:"no_parent,omitempty"`
|
||||
NoDefaultPolicy bool `json:"no_default_policy,omitempty"`
|
||||
DisplayName string `json:"display_name"`
|
||||
NumUses int `json:"num_uses"`
|
||||
Renewable *bool `json:"renewable,omitempty"`
|
||||
Type string `json:"type"`
|
||||
EntityAlias string `json:"entity_alias"`
|
||||
}
|
896
vendor/github.com/hashicorp/vault/api/client.go
generated
vendored
Normal file
896
vendor/github.com/hashicorp/vault/api/client.go
generated
vendored
Normal file
@ -0,0 +1,896 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
rootcerts "github.com/hashicorp/go-rootcerts"
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
const EnvVaultAddress = "VAULT_ADDR"
|
||||
const EnvVaultAgentAddr = "VAULT_AGENT_ADDR"
|
||||
const EnvVaultCACert = "VAULT_CACERT"
|
||||
const EnvVaultCAPath = "VAULT_CAPATH"
|
||||
const EnvVaultClientCert = "VAULT_CLIENT_CERT"
|
||||
const EnvVaultClientKey = "VAULT_CLIENT_KEY"
|
||||
const EnvVaultClientTimeout = "VAULT_CLIENT_TIMEOUT"
|
||||
const EnvVaultSRVLookup = "VAULT_SRV_LOOKUP"
|
||||
const EnvVaultSkipVerify = "VAULT_SKIP_VERIFY"
|
||||
const EnvVaultNamespace = "VAULT_NAMESPACE"
|
||||
const EnvVaultTLSServerName = "VAULT_TLS_SERVER_NAME"
|
||||
const EnvVaultWrapTTL = "VAULT_WRAP_TTL"
|
||||
const EnvVaultMaxRetries = "VAULT_MAX_RETRIES"
|
||||
const EnvVaultToken = "VAULT_TOKEN"
|
||||
const EnvVaultMFA = "VAULT_MFA"
|
||||
const EnvRateLimit = "VAULT_RATE_LIMIT"
|
||||
|
||||
// Deprecated values
|
||||
const EnvVaultAgentAddress = "VAULT_AGENT_ADDR"
|
||||
const EnvVaultInsecure = "VAULT_SKIP_VERIFY"
|
||||
|
||||
// WrappingLookupFunc is a function that, given an HTTP verb and a path,
|
||||
// returns an optional string duration to be used for response wrapping (e.g.
|
||||
// "15s", or simply "15"). The path will not begin with "/v1/" or "v1/" or "/",
|
||||
// however, end-of-path forward slashes are not trimmed, so must match your
|
||||
// called path precisely. Response wrapping will only be used when the return
|
||||
// value is not the empty string.
|
||||
type WrappingLookupFunc func(operation, path string) string
|
||||
|
||||
// Config is used to configure the creation of the client.
|
||||
type Config struct {
|
||||
modifyLock sync.RWMutex
|
||||
|
||||
// Address is the address of the Vault server. This should be a complete
|
||||
// URL such as "http://vault.example.com". If you need a custom SSL
|
||||
// cert or want to enable insecure mode, you need to specify a custom
|
||||
// HttpClient.
|
||||
Address string
|
||||
|
||||
// AgentAddress is the address of the local Vault agent. This should be a
|
||||
// complete URL such as "http://vault.example.com".
|
||||
AgentAddress string
|
||||
|
||||
// HttpClient is the HTTP client to use. Vault sets sane defaults for the
|
||||
// http.Client and its associated http.Transport created in DefaultConfig.
|
||||
// If you must modify Vault's defaults, it is suggested that you start with
|
||||
// that client and modify as needed rather than start with an empty client
|
||||
// (or http.DefaultClient).
|
||||
HttpClient *http.Client
|
||||
|
||||
// MaxRetries controls the maximum number of times to retry when a 5xx
|
||||
// error occurs. Set to 0 to disable retrying. Defaults to 2 (for a total
|
||||
// of three tries).
|
||||
MaxRetries int
|
||||
|
||||
// Timeout is for setting custom timeout parameter in the HttpClient
|
||||
Timeout time.Duration
|
||||
|
||||
// If there is an error when creating the configuration, this will be the
|
||||
// error
|
||||
Error error
|
||||
|
||||
// The Backoff function to use; a default is used if not provided
|
||||
Backoff retryablehttp.Backoff
|
||||
|
||||
// The CheckRetry function to use; a default is used if not provided
|
||||
CheckRetry retryablehttp.CheckRetry
|
||||
|
||||
// Limiter is the rate limiter used by the client.
|
||||
// If this pointer is nil, then there will be no limit set.
|
||||
// In contrast, if this pointer is set, even to an empty struct,
|
||||
// then that limiter will be used. Note that an empty Limiter
|
||||
// is equivalent blocking all events.
|
||||
Limiter *rate.Limiter
|
||||
|
||||
// OutputCurlString causes the actual request to return an error of type
|
||||
// *OutputStringError. Type asserting the error message will allow
|
||||
// fetching a cURL-compatible string for the operation.
|
||||
//
|
||||
// Note: It is not thread-safe to set this and make concurrent requests
|
||||
// with the same client. Cloning a client will not clone this value.
|
||||
OutputCurlString bool
|
||||
|
||||
// SRVLookup enables the client to lookup the host through DNS SRV lookup
|
||||
SRVLookup bool
|
||||
}
|
||||
|
||||
// TLSConfig contains the parameters needed to configure TLS on the HTTP client
|
||||
// used to communicate with Vault.
|
||||
type TLSConfig struct {
|
||||
// CACert is the path to a PEM-encoded CA cert file to use to verify the
|
||||
// Vault server SSL certificate.
|
||||
CACert string
|
||||
|
||||
// CAPath is the path to a directory of PEM-encoded CA cert files to verify
|
||||
// the Vault server SSL certificate.
|
||||
CAPath string
|
||||
|
||||
// ClientCert is the path to the certificate for Vault communication
|
||||
ClientCert string
|
||||
|
||||
// ClientKey is the path to the private key for Vault communication
|
||||
ClientKey string
|
||||
|
||||
// TLSServerName, if set, is used to set the SNI host when connecting via
|
||||
// TLS.
|
||||
TLSServerName string
|
||||
|
||||
// Insecure enables or disables SSL verification
|
||||
Insecure bool
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default configuration for the client. It is
|
||||
// safe to modify the return value of this function.
|
||||
//
|
||||
// The default Address is https://127.0.0.1:8200, but this can be overridden by
|
||||
// setting the `VAULT_ADDR` environment variable.
|
||||
//
|
||||
// If an error is encountered, this will return nil.
|
||||
func DefaultConfig() *Config {
|
||||
config := &Config{
|
||||
Address: "https://127.0.0.1:8200",
|
||||
HttpClient: cleanhttp.DefaultPooledClient(),
|
||||
Timeout: time.Second * 60,
|
||||
}
|
||||
|
||||
transport := config.HttpClient.Transport.(*http.Transport)
|
||||
transport.TLSHandshakeTimeout = 10 * time.Second
|
||||
transport.TLSClientConfig = &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
}
|
||||
if err := http2.ConfigureTransport(transport); err != nil {
|
||||
config.Error = err
|
||||
return config
|
||||
}
|
||||
|
||||
if err := config.ReadEnvironment(); err != nil {
|
||||
config.Error = err
|
||||
return config
|
||||
}
|
||||
|
||||
// Ensure redirects are not automatically followed
|
||||
// Note that this is sane for the API client as it has its own
|
||||
// redirect handling logic (and thus also for command/meta),
|
||||
// but in e.g. http_test actual redirect handling is necessary
|
||||
config.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
// Returning this value causes the Go net library to not close the
|
||||
// response body and to nil out the error. Otherwise retry clients may
|
||||
// try three times on every redirect because it sees an error from this
|
||||
// function (to prevent redirects) passing through to it.
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
config.Backoff = retryablehttp.LinearJitterBackoff
|
||||
config.MaxRetries = 2
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
// ConfigureTLS takes a set of TLS configurations and applies those to the the
|
||||
// HTTP client.
|
||||
func (c *Config) ConfigureTLS(t *TLSConfig) error {
|
||||
if c.HttpClient == nil {
|
||||
c.HttpClient = DefaultConfig().HttpClient
|
||||
}
|
||||
clientTLSConfig := c.HttpClient.Transport.(*http.Transport).TLSClientConfig
|
||||
|
||||
var clientCert tls.Certificate
|
||||
foundClientCert := false
|
||||
|
||||
switch {
|
||||
case t.ClientCert != "" && t.ClientKey != "":
|
||||
var err error
|
||||
clientCert, err = tls.LoadX509KeyPair(t.ClientCert, t.ClientKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
foundClientCert = true
|
||||
case t.ClientCert != "" || t.ClientKey != "":
|
||||
return fmt.Errorf("both client cert and client key must be provided")
|
||||
}
|
||||
|
||||
if t.CACert != "" || t.CAPath != "" {
|
||||
rootConfig := &rootcerts.Config{
|
||||
CAFile: t.CACert,
|
||||
CAPath: t.CAPath,
|
||||
}
|
||||
if err := rootcerts.ConfigureTLS(clientTLSConfig, rootConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if t.Insecure {
|
||||
clientTLSConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
if foundClientCert {
|
||||
// We use this function to ignore the server's preferential list of
|
||||
// CAs, otherwise any CA used for the cert auth backend must be in the
|
||||
// server's CA pool
|
||||
clientTLSConfig.GetClientCertificate = func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
|
||||
return &clientCert, nil
|
||||
}
|
||||
}
|
||||
|
||||
if t.TLSServerName != "" {
|
||||
clientTLSConfig.ServerName = t.TLSServerName
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadEnvironment reads configuration information from the environment. If
|
||||
// there is an error, no configuration value is updated.
|
||||
func (c *Config) ReadEnvironment() error {
|
||||
var envAddress string
|
||||
var envAgentAddress string
|
||||
var envCACert string
|
||||
var envCAPath string
|
||||
var envClientCert string
|
||||
var envClientKey string
|
||||
var envClientTimeout time.Duration
|
||||
var envInsecure bool
|
||||
var envTLSServerName string
|
||||
var envMaxRetries *uint64
|
||||
var envSRVLookup bool
|
||||
var limit *rate.Limiter
|
||||
|
||||
// Parse the environment variables
|
||||
if v := os.Getenv(EnvVaultAddress); v != "" {
|
||||
envAddress = v
|
||||
}
|
||||
if v := os.Getenv(EnvVaultAgentAddr); v != "" {
|
||||
envAgentAddress = v
|
||||
} else if v := os.Getenv(EnvVaultAgentAddress); v != "" {
|
||||
envAgentAddress = v
|
||||
}
|
||||
if v := os.Getenv(EnvVaultMaxRetries); v != "" {
|
||||
maxRetries, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
envMaxRetries = &maxRetries
|
||||
}
|
||||
if v := os.Getenv(EnvVaultCACert); v != "" {
|
||||
envCACert = v
|
||||
}
|
||||
if v := os.Getenv(EnvVaultCAPath); v != "" {
|
||||
envCAPath = v
|
||||
}
|
||||
if v := os.Getenv(EnvVaultClientCert); v != "" {
|
||||
envClientCert = v
|
||||
}
|
||||
if v := os.Getenv(EnvVaultClientKey); v != "" {
|
||||
envClientKey = v
|
||||
}
|
||||
if v := os.Getenv(EnvRateLimit); v != "" {
|
||||
rateLimit, burstLimit, err := parseRateLimit(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
limit = rate.NewLimiter(rate.Limit(rateLimit), burstLimit)
|
||||
}
|
||||
if t := os.Getenv(EnvVaultClientTimeout); t != "" {
|
||||
clientTimeout, err := parseutil.ParseDurationSecond(t)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %q", EnvVaultClientTimeout)
|
||||
}
|
||||
envClientTimeout = clientTimeout
|
||||
}
|
||||
if v := os.Getenv(EnvVaultSkipVerify); v != "" {
|
||||
var err error
|
||||
envInsecure, err = strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse VAULT_SKIP_VERIFY")
|
||||
}
|
||||
} else if v := os.Getenv(EnvVaultInsecure); v != "" {
|
||||
var err error
|
||||
envInsecure, err = strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse VAULT_INSECURE")
|
||||
}
|
||||
}
|
||||
if v := os.Getenv(EnvVaultSRVLookup); v != "" {
|
||||
var err error
|
||||
envSRVLookup, err = strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not parse %s", EnvVaultSRVLookup)
|
||||
}
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvVaultTLSServerName); v != "" {
|
||||
envTLSServerName = v
|
||||
}
|
||||
|
||||
// Configure the HTTP clients TLS configuration.
|
||||
t := &TLSConfig{
|
||||
CACert: envCACert,
|
||||
CAPath: envCAPath,
|
||||
ClientCert: envClientCert,
|
||||
ClientKey: envClientKey,
|
||||
TLSServerName: envTLSServerName,
|
||||
Insecure: envInsecure,
|
||||
}
|
||||
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.SRVLookup = envSRVLookup
|
||||
c.Limiter = limit
|
||||
|
||||
if err := c.ConfigureTLS(t); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if envAddress != "" {
|
||||
c.Address = envAddress
|
||||
}
|
||||
|
||||
if envAgentAddress != "" {
|
||||
c.AgentAddress = envAgentAddress
|
||||
}
|
||||
|
||||
if envMaxRetries != nil {
|
||||
c.MaxRetries = int(*envMaxRetries)
|
||||
}
|
||||
|
||||
if envClientTimeout != 0 {
|
||||
c.Timeout = envClientTimeout
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseRateLimit(val string) (rate float64, burst int, err error) {
|
||||
|
||||
_, err = fmt.Sscanf(val, "%f:%d", &rate, &burst)
|
||||
if err != nil {
|
||||
rate, err = strconv.ParseFloat(val, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("%v was provided but incorrectly formatted", EnvRateLimit)
|
||||
}
|
||||
burst = int(rate)
|
||||
}
|
||||
|
||||
return rate, burst, err
|
||||
|
||||
}
|
||||
|
||||
// Client is the client to the Vault API. Create a client with NewClient.
|
||||
type Client struct {
|
||||
modifyLock sync.RWMutex
|
||||
addr *url.URL
|
||||
config *Config
|
||||
token string
|
||||
headers http.Header
|
||||
wrappingLookupFunc WrappingLookupFunc
|
||||
mfaCreds []string
|
||||
policyOverride bool
|
||||
}
|
||||
|
||||
// NewClient returns a new client for the given configuration.
|
||||
//
|
||||
// If the configuration is nil, Vault will use configuration from
|
||||
// DefaultConfig(), which is the recommended starting configuration.
|
||||
//
|
||||
// If the environment variable `VAULT_TOKEN` is present, the token will be
|
||||
// automatically added to the client. Otherwise, you must manually call
|
||||
// `SetToken()`.
|
||||
func NewClient(c *Config) (*Client, error) {
|
||||
def := DefaultConfig()
|
||||
if def == nil {
|
||||
return nil, fmt.Errorf("could not create/read default configuration")
|
||||
}
|
||||
if def.Error != nil {
|
||||
return nil, errwrap.Wrapf("error encountered setting up default configuration: {{err}}", def.Error)
|
||||
}
|
||||
|
||||
if c == nil {
|
||||
c = def
|
||||
}
|
||||
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
if c.HttpClient == nil {
|
||||
c.HttpClient = def.HttpClient
|
||||
}
|
||||
if c.HttpClient.Transport == nil {
|
||||
c.HttpClient.Transport = def.HttpClient.Transport
|
||||
}
|
||||
|
||||
address := c.Address
|
||||
if c.AgentAddress != "" {
|
||||
address = c.AgentAddress
|
||||
}
|
||||
|
||||
u, err := url.Parse(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.HasPrefix(address, "unix://") {
|
||||
socket := strings.TrimPrefix(address, "unix://")
|
||||
transport := c.HttpClient.Transport.(*http.Transport)
|
||||
transport.DialContext = func(context.Context, string, string) (net.Conn, error) {
|
||||
return net.Dial("unix", socket)
|
||||
}
|
||||
|
||||
// Since the address points to a unix domain socket, the scheme in the
|
||||
// *URL would be set to `unix`. The *URL in the client is expected to
|
||||
// be pointing to the protocol used in the application layer and not to
|
||||
// the transport layer. Hence, setting the fields accordingly.
|
||||
u.Scheme = "http"
|
||||
u.Host = socket
|
||||
u.Path = ""
|
||||
}
|
||||
|
||||
client := &Client{
|
||||
addr: u,
|
||||
config: c,
|
||||
headers: make(http.Header),
|
||||
}
|
||||
|
||||
// Add the VaultRequest SSRF protection header
|
||||
client.headers[consts.RequestHeaderName] = []string{"true"}
|
||||
|
||||
if token := os.Getenv(EnvVaultToken); token != "" {
|
||||
client.token = token
|
||||
}
|
||||
|
||||
if namespace := os.Getenv(EnvVaultNamespace); namespace != "" {
|
||||
client.setNamespace(namespace)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Sets the address of Vault in the client. The format of address should be
|
||||
// "<Scheme>://<Host>:<Port>". Setting this on a client will override the
|
||||
// value of VAULT_ADDR environment variable.
|
||||
func (c *Client) SetAddress(addr string) error {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
parsedAddr, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("failed to set address: {{err}}", err)
|
||||
}
|
||||
|
||||
c.addr = parsedAddr
|
||||
return nil
|
||||
}
|
||||
|
||||
// Address returns the Vault URL the client is configured to connect to
|
||||
func (c *Client) Address() string {
|
||||
c.modifyLock.RLock()
|
||||
defer c.modifyLock.RUnlock()
|
||||
|
||||
return c.addr.String()
|
||||
}
|
||||
|
||||
// SetLimiter will set the rate limiter for this client.
|
||||
// This method is thread-safe.
|
||||
// rateLimit and burst are specified according to https://godoc.org/golang.org/x/time/rate#NewLimiter
|
||||
func (c *Client) SetLimiter(rateLimit float64, burst int) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.Limiter = rate.NewLimiter(rate.Limit(rateLimit), burst)
|
||||
}
|
||||
|
||||
// SetMaxRetries sets the number of retries that will be used in the case of certain errors
|
||||
func (c *Client) SetMaxRetries(retries int) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.MaxRetries = retries
|
||||
}
|
||||
|
||||
// SetCheckRetry sets the CheckRetry function to be used for future requests.
|
||||
func (c *Client) SetCheckRetry(checkRetry retryablehttp.CheckRetry) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.CheckRetry = checkRetry
|
||||
}
|
||||
|
||||
// SetClientTimeout sets the client request timeout
|
||||
func (c *Client) SetClientTimeout(timeout time.Duration) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.Timeout = timeout
|
||||
}
|
||||
|
||||
func (c *Client) OutputCurlString() bool {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.RLock()
|
||||
defer c.config.modifyLock.RUnlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
return c.config.OutputCurlString
|
||||
}
|
||||
|
||||
func (c *Client) SetOutputCurlString(curl bool) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.OutputCurlString = curl
|
||||
}
|
||||
|
||||
// CurrentWrappingLookupFunc sets a lookup function that returns desired wrap TTLs
|
||||
// for a given operation and path.
|
||||
func (c *Client) CurrentWrappingLookupFunc() WrappingLookupFunc {
|
||||
c.modifyLock.RLock()
|
||||
defer c.modifyLock.RUnlock()
|
||||
|
||||
return c.wrappingLookupFunc
|
||||
}
|
||||
|
||||
// SetWrappingLookupFunc sets a lookup function that returns desired wrap TTLs
|
||||
// for a given operation and path.
|
||||
func (c *Client) SetWrappingLookupFunc(lookupFunc WrappingLookupFunc) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.wrappingLookupFunc = lookupFunc
|
||||
}
|
||||
|
||||
// SetMFACreds sets the MFA credentials supplied either via the environment
|
||||
// variable or via the command line.
|
||||
func (c *Client) SetMFACreds(creds []string) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.mfaCreds = creds
|
||||
}
|
||||
|
||||
// SetNamespace sets the namespace supplied either via the environment
|
||||
// variable or via the command line.
|
||||
func (c *Client) SetNamespace(namespace string) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
c.setNamespace(namespace)
|
||||
}
|
||||
|
||||
func (c *Client) setNamespace(namespace string) {
|
||||
if c.headers == nil {
|
||||
c.headers = make(http.Header)
|
||||
}
|
||||
|
||||
c.headers.Set(consts.NamespaceHeaderName, namespace)
|
||||
}
|
||||
|
||||
// Token returns the access token being used by this client. It will
|
||||
// return the empty string if there is no token set.
|
||||
func (c *Client) Token() string {
|
||||
c.modifyLock.RLock()
|
||||
defer c.modifyLock.RUnlock()
|
||||
|
||||
return c.token
|
||||
}
|
||||
|
||||
// SetToken sets the token directly. This won't perform any auth
|
||||
// verification, it simply sets the token properly for future requests.
|
||||
func (c *Client) SetToken(v string) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.token = v
|
||||
}
|
||||
|
||||
// ClearToken deletes the token if it is set or does nothing otherwise.
|
||||
func (c *Client) ClearToken() {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.token = ""
|
||||
}
|
||||
|
||||
// Headers gets the current set of headers used for requests. This returns a
|
||||
// copy; to modify it call AddHeader or SetHeaders.
|
||||
func (c *Client) Headers() http.Header {
|
||||
c.modifyLock.RLock()
|
||||
defer c.modifyLock.RUnlock()
|
||||
|
||||
if c.headers == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
ret := make(http.Header)
|
||||
for k, v := range c.headers {
|
||||
for _, val := range v {
|
||||
ret[k] = append(ret[k], val)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// AddHeader allows a single header key/value pair to be added
|
||||
// in a race-safe fashion.
|
||||
func (c *Client) AddHeader(key, value string) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
c.headers.Add(key, value)
|
||||
}
|
||||
|
||||
// SetHeaders clears all previous headers and uses only the given
|
||||
// ones going forward.
|
||||
func (c *Client) SetHeaders(headers http.Header) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
c.headers = headers
|
||||
}
|
||||
|
||||
// SetBackoff sets the backoff function to be used for future requests.
|
||||
func (c *Client) SetBackoff(backoff retryablehttp.Backoff) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.Backoff = backoff
|
||||
}
|
||||
|
||||
// Clone creates a new client with the same configuration. Note that the same
|
||||
// underlying http.Client is used; modifying the client from more than one
|
||||
// goroutine at once may not be safe, so modify the client as needed and then
|
||||
// clone.
|
||||
//
|
||||
// Also, only the client's config is currently copied; this means items not in
|
||||
// the api.Config struct, such as policy override and wrapping function
|
||||
// behavior, must currently then be set as desired on the new client.
|
||||
func (c *Client) Clone() (*Client, error) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.RLock()
|
||||
config := c.config
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
newConfig := &Config{
|
||||
Address: config.Address,
|
||||
HttpClient: config.HttpClient,
|
||||
MaxRetries: config.MaxRetries,
|
||||
Timeout: config.Timeout,
|
||||
Backoff: config.Backoff,
|
||||
CheckRetry: config.CheckRetry,
|
||||
Limiter: config.Limiter,
|
||||
}
|
||||
config.modifyLock.RUnlock()
|
||||
|
||||
return NewClient(newConfig)
|
||||
}
|
||||
|
||||
// SetPolicyOverride sets whether requests should be sent with the policy
|
||||
// override flag to request overriding soft-mandatory Sentinel policies (both
|
||||
// RGPs and EGPs)
|
||||
func (c *Client) SetPolicyOverride(override bool) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.policyOverride = override
|
||||
}
|
||||
|
||||
// NewRequest creates a new raw request object to query the Vault server
|
||||
// configured for this client. This is an advanced method and generally
|
||||
// doesn't need to be called externally.
|
||||
func (c *Client) NewRequest(method, requestPath string) *Request {
|
||||
c.modifyLock.RLock()
|
||||
addr := c.addr
|
||||
token := c.token
|
||||
mfaCreds := c.mfaCreds
|
||||
wrappingLookupFunc := c.wrappingLookupFunc
|
||||
policyOverride := c.policyOverride
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
var host = addr.Host
|
||||
// if SRV records exist (see https://tools.ietf.org/html/draft-andrews-http-srv-02), lookup the SRV
|
||||
// record and take the highest match; this is not designed for high-availability, just discovery
|
||||
// Internet Draft specifies that the SRV record is ignored if a port is given
|
||||
if addr.Port() == "" && c.config.SRVLookup {
|
||||
_, addrs, err := net.LookupSRV("http", "tcp", addr.Hostname())
|
||||
if err == nil && len(addrs) > 0 {
|
||||
host = fmt.Sprintf("%s:%d", addrs[0].Target, addrs[0].Port)
|
||||
}
|
||||
}
|
||||
|
||||
req := &Request{
|
||||
Method: method,
|
||||
URL: &url.URL{
|
||||
User: addr.User,
|
||||
Scheme: addr.Scheme,
|
||||
Host: host,
|
||||
Path: path.Join(addr.Path, requestPath),
|
||||
},
|
||||
Host: addr.Host,
|
||||
ClientToken: token,
|
||||
Params: make(map[string][]string),
|
||||
}
|
||||
|
||||
var lookupPath string
|
||||
switch {
|
||||
case strings.HasPrefix(requestPath, "/v1/"):
|
||||
lookupPath = strings.TrimPrefix(requestPath, "/v1/")
|
||||
case strings.HasPrefix(requestPath, "v1/"):
|
||||
lookupPath = strings.TrimPrefix(requestPath, "v1/")
|
||||
default:
|
||||
lookupPath = requestPath
|
||||
}
|
||||
|
||||
req.MFAHeaderVals = mfaCreds
|
||||
|
||||
if wrappingLookupFunc != nil {
|
||||
req.WrapTTL = wrappingLookupFunc(method, lookupPath)
|
||||
} else {
|
||||
req.WrapTTL = DefaultWrappingLookupFunc(method, lookupPath)
|
||||
}
|
||||
|
||||
req.Headers = c.Headers()
|
||||
req.PolicyOverride = policyOverride
|
||||
|
||||
return req
|
||||
}
|
||||
|
||||
// RawRequest performs the raw request given. This request may be against
|
||||
// a Vault server not configured with this client. This is an advanced operation
|
||||
// that generally won't need to be called externally.
|
||||
func (c *Client) RawRequest(r *Request) (*Response, error) {
|
||||
return c.RawRequestWithContext(context.Background(), r)
|
||||
}
|
||||
|
||||
// RawRequestWithContext performs the raw request given. This request may be against
|
||||
// a Vault server not configured with this client. This is an advanced operation
|
||||
// that generally won't need to be called externally.
|
||||
func (c *Client) RawRequestWithContext(ctx context.Context, r *Request) (*Response, error) {
|
||||
c.modifyLock.RLock()
|
||||
token := c.token
|
||||
|
||||
c.config.modifyLock.RLock()
|
||||
limiter := c.config.Limiter
|
||||
maxRetries := c.config.MaxRetries
|
||||
checkRetry := c.config.CheckRetry
|
||||
backoff := c.config.Backoff
|
||||
httpClient := c.config.HttpClient
|
||||
timeout := c.config.Timeout
|
||||
outputCurlString := c.config.OutputCurlString
|
||||
c.config.modifyLock.RUnlock()
|
||||
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
if limiter != nil {
|
||||
limiter.Wait(ctx)
|
||||
}
|
||||
|
||||
// Sanity check the token before potentially erroring from the API
|
||||
idx := strings.IndexFunc(token, func(c rune) bool {
|
||||
return !unicode.IsPrint(c)
|
||||
})
|
||||
if idx != -1 {
|
||||
return nil, fmt.Errorf("configured Vault token contains non-printable characters and cannot be used")
|
||||
}
|
||||
|
||||
redirectCount := 0
|
||||
START:
|
||||
req, err := r.toRetryableHTTP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("nil request created")
|
||||
}
|
||||
|
||||
if outputCurlString {
|
||||
LastOutputStringError = &OutputStringError{Request: req}
|
||||
return nil, LastOutputStringError
|
||||
}
|
||||
|
||||
if timeout != 0 {
|
||||
// Note: we purposefully do not call cancel manually. The reason is
|
||||
// when canceled, the request.Body will EOF when reading due to the way
|
||||
// it streams data in. Cancel will still be run when the timeout is
|
||||
// hit, so this doesn't really harm anything.
|
||||
ctx, _ = context.WithTimeout(ctx, timeout)
|
||||
}
|
||||
req.Request = req.Request.WithContext(ctx)
|
||||
|
||||
if backoff == nil {
|
||||
backoff = retryablehttp.LinearJitterBackoff
|
||||
}
|
||||
|
||||
if checkRetry == nil {
|
||||
checkRetry = retryablehttp.DefaultRetryPolicy
|
||||
}
|
||||
|
||||
client := &retryablehttp.Client{
|
||||
HTTPClient: httpClient,
|
||||
RetryWaitMin: 1000 * time.Millisecond,
|
||||
RetryWaitMax: 1500 * time.Millisecond,
|
||||
RetryMax: maxRetries,
|
||||
Backoff: backoff,
|
||||
CheckRetry: checkRetry,
|
||||
ErrorHandler: retryablehttp.PassthroughErrorHandler,
|
||||
}
|
||||
|
||||
var result *Response
|
||||
resp, err := client.Do(req)
|
||||
if resp != nil {
|
||||
result = &Response{Response: resp}
|
||||
}
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "tls: oversized") {
|
||||
err = errwrap.Wrapf(
|
||||
"{{err}}\n\n"+
|
||||
"This error usually means that the server is running with TLS disabled\n"+
|
||||
"but the client is configured to use TLS. Please either enable TLS\n"+
|
||||
"on the server or run the client with -address set to an address\n"+
|
||||
"that uses the http protocol:\n\n"+
|
||||
" vault <command> -address http://<address>\n\n"+
|
||||
"You can also set the VAULT_ADDR environment variable:\n\n\n"+
|
||||
" VAULT_ADDR=http://<address> vault <command>\n\n"+
|
||||
"where <address> is replaced by the actual address to the server.",
|
||||
err)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Check for a redirect, only allowing for a single redirect
|
||||
if (resp.StatusCode == 301 || resp.StatusCode == 302 || resp.StatusCode == 307) && redirectCount == 0 {
|
||||
// Parse the updated location
|
||||
respLoc, err := resp.Location()
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Ensure a protocol downgrade doesn't happen
|
||||
if req.URL.Scheme == "https" && respLoc.Scheme != "https" {
|
||||
return result, fmt.Errorf("redirect would cause protocol downgrade")
|
||||
}
|
||||
|
||||
// Update the request
|
||||
r.URL = respLoc
|
||||
|
||||
// Reset the request body if any
|
||||
if err := r.ResetJSONBody(); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Retry the request
|
||||
redirectCount++
|
||||
goto START
|
||||
}
|
||||
|
||||
if err := result.Error(); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
20
vendor/github.com/hashicorp/vault/api/go.mod
generated
vendored
Normal file
20
vendor/github.com/hashicorp/vault/api/go.mod
generated
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
module github.com/hashicorp/vault/api
|
||||
|
||||
go 1.13
|
||||
|
||||
replace github.com/hashicorp/vault/sdk => ../sdk
|
||||
|
||||
require (
|
||||
github.com/go-test/deep v1.0.2
|
||||
github.com/hashicorp/errwrap v1.0.0
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1
|
||||
github.com/hashicorp/go-multierror v1.1.0
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6
|
||||
github.com/hashicorp/go-rootcerts v1.0.2
|
||||
github.com/hashicorp/hcl v1.0.0
|
||||
github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267
|
||||
github.com/mitchellh/mapstructure v1.3.2
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1
|
||||
gopkg.in/square/go-jose.v2 v2.5.1
|
||||
)
|
357
vendor/github.com/hashicorp/vault/api/go.sum
generated
vendored
Normal file
357
vendor/github.com/hashicorp/vault/api/go.sum
generated
vendored
Normal file
@ -0,0 +1,357 @@
|
||||
bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
|
||||
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||
github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
|
||||
github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
|
||||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v1.4.2-0.20200319182547-c7ad2b866182/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/frankban/quicktest v1.10.0 h1:Gfh+GAJZOAoKZsIZeZbdn2JF10kN1XHNvjsvQK8gVkE=
|
||||
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM=
|
||||
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
|
||||
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
|
||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.2 h1:bHM2aVXwBtBJWxHtkSrWuI4umABCUczs52eiUS9nSiw=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
|
||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
|
||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
|
||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
|
||||
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
|
||||
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7 h1:fHDIZ2oxGnUZRN6WgWFCbYBjH9uqVPRCUVUDhs0wnbA=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
|
||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
|
||||
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
|
||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4=
|
||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
30
vendor/github.com/hashicorp/vault/api/help.go
generated
vendored
Normal file
30
vendor/github.com/hashicorp/vault/api/help.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Help reads the help information for the given path.
|
||||
func (c *Client) Help(path string) (*Help, error) {
|
||||
r := c.NewRequest("GET", fmt.Sprintf("/v1/%s", path))
|
||||
r.Params.Add("help", "1")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result Help
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type Help struct {
|
||||
Help string `json:"help"`
|
||||
SeeAlso []string `json:"see_also"`
|
||||
OpenAPI map[string]interface{} `json:"openapi"`
|
||||
}
|
384
vendor/github.com/hashicorp/vault/api/lifetime_watcher.go
generated
vendored
Normal file
384
vendor/github.com/hashicorp/vault/api/lifetime_watcher.go
generated
vendored
Normal file
@ -0,0 +1,384 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrLifetimeWatcherMissingInput = errors.New("missing input")
|
||||
ErrLifetimeWatcherMissingSecret = errors.New("missing secret")
|
||||
ErrLifetimeWatcherNotRenewable = errors.New("secret is not renewable")
|
||||
ErrLifetimeWatcherNoSecretData = errors.New("returned empty secret data")
|
||||
|
||||
// Deprecated; kept for compatibility
|
||||
ErrRenewerMissingInput = errors.New("missing input to renewer")
|
||||
ErrRenewerMissingSecret = errors.New("missing secret to renew")
|
||||
ErrRenewerNotRenewable = errors.New("secret is not renewable")
|
||||
ErrRenewerNoSecretData = errors.New("returned empty secret data")
|
||||
|
||||
// DefaultLifetimeWatcherRenewBuffer is the default size of the buffer for renew
|
||||
// messages on the channel.
|
||||
DefaultLifetimeWatcherRenewBuffer = 5
|
||||
// Deprecated: kept for backwards compatibility
|
||||
DefaultRenewerRenewBuffer = 5
|
||||
)
|
||||
|
||||
type RenewBehavior uint
|
||||
|
||||
const (
|
||||
// RenewBehaviorIgnoreErrors means we will attempt to keep renewing until
|
||||
// we hit the lifetime threshold. It also ignores errors stemming from
|
||||
// passing a non-renewable lease in. In practice, this means you simply
|
||||
// reauthenticate/refetch credentials when the watcher exits. This is the
|
||||
// default.
|
||||
RenewBehaviorIgnoreErrors RenewBehavior = iota
|
||||
|
||||
// RenewBehaviorRenewDisabled turns off renewal attempts entirely. This
|
||||
// allows you to simply watch lifetime and have the watcher return at a
|
||||
// reasonable threshold without actually making Vault calls.
|
||||
RenewBehaviorRenewDisabled
|
||||
|
||||
// RenewBehaviorErrorOnErrors is the "legacy" behavior which always exits
|
||||
// on some kind of error
|
||||
RenewBehaviorErrorOnErrors
|
||||
)
|
||||
|
||||
// LifetimeWatcher is a process for watching lifetime of a secret.
|
||||
//
|
||||
// watcher, err := client.NewLifetimeWatcher(&LifetimeWatcherInput{
|
||||
// Secret: mySecret,
|
||||
// })
|
||||
// go watcher.Start()
|
||||
// defer watcher.Stop()
|
||||
//
|
||||
// for {
|
||||
// select {
|
||||
// case err := <-watcher.DoneCh():
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// // Renewal is now over
|
||||
// case renewal := <-watcher.RenewCh():
|
||||
// log.Printf("Successfully renewed: %#v", renewal)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//
|
||||
// `DoneCh` will return if renewal fails, or if the remaining lease duration is
|
||||
// under a built-in threshold and either renewing is not extending it or
|
||||
// renewing is disabled. In both cases, the caller should attempt a re-read of
|
||||
// the secret. Clients should check the return value of the channel to see if
|
||||
// renewal was successful.
|
||||
type LifetimeWatcher struct {
|
||||
l sync.Mutex
|
||||
|
||||
client *Client
|
||||
secret *Secret
|
||||
grace time.Duration
|
||||
random *rand.Rand
|
||||
increment int
|
||||
doneCh chan error
|
||||
renewCh chan *RenewOutput
|
||||
renewBehavior RenewBehavior
|
||||
|
||||
stopped bool
|
||||
stopCh chan struct{}
|
||||
|
||||
errLifetimeWatcherNotRenewable error
|
||||
errLifetimeWatcherNoSecretData error
|
||||
}
|
||||
|
||||
// LifetimeWatcherInput is used as input to the renew function.
|
||||
type LifetimeWatcherInput struct {
|
||||
// Secret is the secret to renew
|
||||
Secret *Secret
|
||||
|
||||
// DEPRECATED: this does not do anything.
|
||||
Grace time.Duration
|
||||
|
||||
// Rand is the randomizer to use for underlying randomization. If not
|
||||
// provided, one will be generated and seeded automatically. If provided, it
|
||||
// is assumed to have already been seeded.
|
||||
Rand *rand.Rand
|
||||
|
||||
// RenewBuffer is the size of the buffered channel where renew messages are
|
||||
// dispatched.
|
||||
RenewBuffer int
|
||||
|
||||
// The new TTL, in seconds, that should be set on the lease. The TTL set
|
||||
// here may or may not be honored by the vault server, based on Vault
|
||||
// configuration or any associated max TTL values.
|
||||
Increment int
|
||||
|
||||
// RenewBehavior controls what happens when a renewal errors or the
|
||||
// passed-in secret is not renewable.
|
||||
RenewBehavior RenewBehavior
|
||||
}
|
||||
|
||||
// RenewOutput is the metadata returned to the client (if it's listening) to
|
||||
// renew messages.
|
||||
type RenewOutput struct {
|
||||
// RenewedAt is the timestamp when the renewal took place (UTC).
|
||||
RenewedAt time.Time
|
||||
|
||||
// Secret is the underlying renewal data. It's the same struct as all data
|
||||
// that is returned from Vault, but since this is renewal data, it will not
|
||||
// usually include the secret itself.
|
||||
Secret *Secret
|
||||
}
|
||||
|
||||
// NewLifetimeWatcher creates a new renewer from the given input.
|
||||
func (c *Client) NewLifetimeWatcher(i *LifetimeWatcherInput) (*LifetimeWatcher, error) {
|
||||
if i == nil {
|
||||
return nil, ErrLifetimeWatcherMissingInput
|
||||
}
|
||||
|
||||
secret := i.Secret
|
||||
if secret == nil {
|
||||
return nil, ErrLifetimeWatcherMissingSecret
|
||||
}
|
||||
|
||||
random := i.Rand
|
||||
if random == nil {
|
||||
random = rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
|
||||
}
|
||||
|
||||
renewBuffer := i.RenewBuffer
|
||||
if renewBuffer == 0 {
|
||||
renewBuffer = DefaultLifetimeWatcherRenewBuffer
|
||||
}
|
||||
|
||||
return &LifetimeWatcher{
|
||||
client: c,
|
||||
secret: secret,
|
||||
increment: i.Increment,
|
||||
random: random,
|
||||
doneCh: make(chan error, 1),
|
||||
renewCh: make(chan *RenewOutput, renewBuffer),
|
||||
renewBehavior: i.RenewBehavior,
|
||||
|
||||
stopped: false,
|
||||
stopCh: make(chan struct{}),
|
||||
|
||||
errLifetimeWatcherNotRenewable: ErrLifetimeWatcherNotRenewable,
|
||||
errLifetimeWatcherNoSecretData: ErrLifetimeWatcherNoSecretData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Deprecated: exists only for backwards compatibility. Calls
|
||||
// NewLifetimeWatcher, and sets compatibility flags.
|
||||
func (c *Client) NewRenewer(i *LifetimeWatcherInput) (*LifetimeWatcher, error) {
|
||||
if i == nil {
|
||||
return nil, ErrRenewerMissingInput
|
||||
}
|
||||
|
||||
secret := i.Secret
|
||||
if secret == nil {
|
||||
return nil, ErrRenewerMissingSecret
|
||||
}
|
||||
|
||||
renewer, err := c.NewLifetimeWatcher(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
renewer.renewBehavior = RenewBehaviorErrorOnErrors
|
||||
renewer.errLifetimeWatcherNotRenewable = ErrRenewerNotRenewable
|
||||
renewer.errLifetimeWatcherNoSecretData = ErrRenewerNoSecretData
|
||||
return renewer, err
|
||||
}
|
||||
|
||||
// DoneCh returns the channel where the renewer will publish when renewal stops.
|
||||
// If there is an error, this will be an error.
|
||||
func (r *LifetimeWatcher) DoneCh() <-chan error {
|
||||
return r.doneCh
|
||||
}
|
||||
|
||||
// RenewCh is a channel that receives a message when a successful renewal takes
|
||||
// place and includes metadata about the renewal.
|
||||
func (r *LifetimeWatcher) RenewCh() <-chan *RenewOutput {
|
||||
return r.renewCh
|
||||
}
|
||||
|
||||
// Stop stops the renewer.
|
||||
func (r *LifetimeWatcher) Stop() {
|
||||
r.l.Lock()
|
||||
defer r.l.Unlock()
|
||||
|
||||
if !r.stopped {
|
||||
close(r.stopCh)
|
||||
r.stopped = true
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts a background process for watching the lifetime of this secret.
|
||||
// If renewal is enabled, when the secret has auth data, this attempts to renew
|
||||
// the auth (token); When the secret has a lease, this attempts to renew the
|
||||
// lease.
|
||||
func (r *LifetimeWatcher) Start() {
|
||||
r.doneCh <- r.doRenew()
|
||||
}
|
||||
|
||||
// Renew is for comnpatibility with the legacy api.Renewer. Calling Renew
|
||||
// simply chains to Start.
|
||||
func (r *LifetimeWatcher) Renew() {
|
||||
r.Start()
|
||||
}
|
||||
|
||||
// renewAuth is a helper for renewing authentication.
|
||||
func (r *LifetimeWatcher) doRenew() error {
|
||||
var nonRenewable bool
|
||||
var tokenMode bool
|
||||
var initLeaseDuration int
|
||||
var credString string
|
||||
var renewFunc func(string, int) (*Secret, error)
|
||||
|
||||
switch {
|
||||
case r.secret.Auth != nil:
|
||||
tokenMode = true
|
||||
nonRenewable = !r.secret.Auth.Renewable
|
||||
initLeaseDuration = r.secret.Auth.LeaseDuration
|
||||
credString = r.secret.Auth.ClientToken
|
||||
renewFunc = r.client.Auth().Token().RenewTokenAsSelf
|
||||
default:
|
||||
nonRenewable = !r.secret.Renewable
|
||||
initLeaseDuration = r.secret.LeaseDuration
|
||||
credString = r.secret.LeaseID
|
||||
renewFunc = r.client.Sys().Renew
|
||||
}
|
||||
|
||||
if credString == "" ||
|
||||
(nonRenewable && r.renewBehavior == RenewBehaviorErrorOnErrors) {
|
||||
return r.errLifetimeWatcherNotRenewable
|
||||
}
|
||||
|
||||
initialTime := time.Now()
|
||||
priorDuration := time.Duration(initLeaseDuration) * time.Second
|
||||
r.calculateGrace(priorDuration)
|
||||
|
||||
for {
|
||||
// Check if we are stopped.
|
||||
select {
|
||||
case <-r.stopCh:
|
||||
return nil
|
||||
default:
|
||||
}
|
||||
|
||||
var leaseDuration time.Duration
|
||||
fallbackLeaseDuration := initialTime.Add(priorDuration).Sub(time.Now())
|
||||
|
||||
switch {
|
||||
case nonRenewable || r.renewBehavior == RenewBehaviorRenewDisabled:
|
||||
// Can't or won't renew, just keep the same expiration so we exit
|
||||
// when it's reauthentication time
|
||||
leaseDuration = fallbackLeaseDuration
|
||||
|
||||
default:
|
||||
// Renew the token
|
||||
renewal, err := renewFunc(credString, r.increment)
|
||||
if err != nil || renewal == nil || (tokenMode && renewal.Auth == nil) {
|
||||
if r.renewBehavior == RenewBehaviorErrorOnErrors {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if renewal == nil || (tokenMode && renewal.Auth == nil) {
|
||||
return r.errLifetimeWatcherNoSecretData
|
||||
}
|
||||
}
|
||||
|
||||
leaseDuration = fallbackLeaseDuration
|
||||
break
|
||||
}
|
||||
|
||||
// Push a message that a renewal took place.
|
||||
select {
|
||||
case r.renewCh <- &RenewOutput{time.Now().UTC(), renewal}:
|
||||
default:
|
||||
}
|
||||
|
||||
// Possibly error if we are not renewable
|
||||
if ((tokenMode && !renewal.Auth.Renewable) || (!tokenMode && !renewal.Renewable)) &&
|
||||
r.renewBehavior == RenewBehaviorErrorOnErrors {
|
||||
return r.errLifetimeWatcherNotRenewable
|
||||
}
|
||||
|
||||
// Grab the lease duration
|
||||
newDuration := renewal.LeaseDuration
|
||||
if tokenMode {
|
||||
newDuration = renewal.Auth.LeaseDuration
|
||||
}
|
||||
|
||||
leaseDuration = time.Duration(newDuration) * time.Second
|
||||
}
|
||||
|
||||
// We keep evaluating a new grace period so long as the lease is
|
||||
// extending. Once it stops extending, we've hit the max and need to
|
||||
// rely on the grace duration.
|
||||
if leaseDuration > priorDuration {
|
||||
r.calculateGrace(leaseDuration)
|
||||
}
|
||||
priorDuration = leaseDuration
|
||||
|
||||
// The sleep duration is set to 2/3 of the current lease duration plus
|
||||
// 1/3 of the current grace period, which adds jitter.
|
||||
sleepDuration := time.Duration(float64(leaseDuration.Nanoseconds())*2/3 + float64(r.grace.Nanoseconds())/3)
|
||||
|
||||
// If we are within grace, return now; or, if the amount of time we
|
||||
// would sleep would land us in the grace period. This helps with short
|
||||
// tokens; for example, you don't want a current lease duration of 4
|
||||
// seconds, a grace period of 3 seconds, and end up sleeping for more
|
||||
// than three of those seconds and having a very small budget of time
|
||||
// to renew.
|
||||
if leaseDuration <= r.grace || leaseDuration-sleepDuration <= r.grace {
|
||||
return nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-r.stopCh:
|
||||
return nil
|
||||
case <-time.After(sleepDuration):
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sleepDuration calculates the time to sleep given the base lease duration. The
|
||||
// base is the resulting lease duration. It will be reduced to 1/3 and
|
||||
// multiplied by a random float between 0.0 and 1.0. This extra randomness
|
||||
// prevents multiple clients from all trying to renew simultaneously.
|
||||
func (r *LifetimeWatcher) sleepDuration(base time.Duration) time.Duration {
|
||||
sleep := float64(base)
|
||||
|
||||
// Renew at 1/3 the remaining lease. This will give us an opportunity to retry
|
||||
// at least one more time should the first renewal fail.
|
||||
sleep = sleep / 3.0
|
||||
|
||||
// Use a randomness so many clients do not hit Vault simultaneously.
|
||||
sleep = sleep * (r.random.Float64() + 1) / 2.0
|
||||
|
||||
return time.Duration(sleep)
|
||||
}
|
||||
|
||||
// calculateGrace calculates the grace period based on a reasonable set of
|
||||
// assumptions given the total lease time; it also adds some jitter to not have
|
||||
// clients be in sync.
|
||||
func (r *LifetimeWatcher) calculateGrace(leaseDuration time.Duration) {
|
||||
if leaseDuration == 0 {
|
||||
r.grace = 0
|
||||
return
|
||||
}
|
||||
|
||||
leaseNanos := float64(leaseDuration.Nanoseconds())
|
||||
jitterMax := 0.1 * leaseNanos
|
||||
|
||||
// For a given lease duration, we want to allow 80-90% of that to elapse,
|
||||
// so the remaining amount is the grace period
|
||||
r.grace = time.Duration(jitterMax) + time.Duration(uint64(r.random.Int63())%uint64(jitterMax))
|
||||
}
|
||||
|
||||
type Renewer = LifetimeWatcher
|
||||
type RenewerInput = LifetimeWatcherInput
|
297
vendor/github.com/hashicorp/vault/api/logical.go
generated
vendored
Normal file
297
vendor/github.com/hashicorp/vault/api/logical.go
generated
vendored
Normal file
@ -0,0 +1,297 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
)
|
||||
|
||||
const (
|
||||
wrappedResponseLocation = "cubbyhole/response"
|
||||
)
|
||||
|
||||
var (
|
||||
// The default TTL that will be used with `sys/wrapping/wrap`, can be
|
||||
// changed
|
||||
DefaultWrappingTTL = "5m"
|
||||
|
||||
// The default function used if no other function is set. It honors the env
|
||||
// var to set the wrap TTL. The default wrap TTL will apply when when writing
|
||||
// to `sys/wrapping/wrap` when the env var is not set.
|
||||
DefaultWrappingLookupFunc = func(operation, path string) string {
|
||||
if os.Getenv(EnvVaultWrapTTL) != "" {
|
||||
return os.Getenv(EnvVaultWrapTTL)
|
||||
}
|
||||
|
||||
if (operation == "PUT" || operation == "POST") && path == "sys/wrapping/wrap" {
|
||||
return DefaultWrappingTTL
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
)
|
||||
|
||||
// Logical is used to perform logical backend operations on Vault.
|
||||
type Logical struct {
|
||||
c *Client
|
||||
}
|
||||
|
||||
// Logical is used to return the client for logical-backend API calls.
|
||||
func (c *Client) Logical() *Logical {
|
||||
return &Logical{c: c}
|
||||
}
|
||||
|
||||
func (c *Logical) Read(path string) (*Secret, error) {
|
||||
return c.ReadWithData(path, nil)
|
||||
}
|
||||
|
||||
func (c *Logical) ReadWithData(path string, data map[string][]string) (*Secret, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/"+path)
|
||||
|
||||
var values url.Values
|
||||
for k, v := range data {
|
||||
if values == nil {
|
||||
values = make(url.Values)
|
||||
}
|
||||
for _, val := range v {
|
||||
values.Add(k, val)
|
||||
}
|
||||
}
|
||||
|
||||
if values != nil {
|
||||
r.Params = values
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
switch parseErr {
|
||||
case nil:
|
||||
case io.EOF:
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if secret != nil && (len(secret.Warnings) > 0 || len(secret.Data) > 0) {
|
||||
return secret, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Logical) List(path string) (*Secret, error) {
|
||||
r := c.c.NewRequest("LIST", "/v1/"+path)
|
||||
// Set this for broader compatibility, but we use LIST above to be able to
|
||||
// handle the wrapping lookup function
|
||||
r.Method = "GET"
|
||||
r.Params.Set("list", "true")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
switch parseErr {
|
||||
case nil:
|
||||
case io.EOF:
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if secret != nil && (len(secret.Warnings) > 0 || len(secret.Data) > 0) {
|
||||
return secret, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Logical) Write(path string, data map[string]interface{}) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/"+path)
|
||||
if err := r.SetJSONBody(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.write(path, r)
|
||||
}
|
||||
|
||||
func (c *Logical) WriteBytes(path string, data []byte) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/"+path)
|
||||
r.BodyBytes = data
|
||||
|
||||
return c.write(path, r)
|
||||
}
|
||||
|
||||
func (c *Logical) write(path string, request *Request) (*Secret, error) {
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, request)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
switch parseErr {
|
||||
case nil:
|
||||
case io.EOF:
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if secret != nil && (len(secret.Warnings) > 0 || len(secret.Data) > 0) {
|
||||
return secret, err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Logical) Delete(path string) (*Secret, error) {
|
||||
return c.DeleteWithData(path, nil)
|
||||
}
|
||||
|
||||
func (c *Logical) DeleteWithData(path string, data map[string][]string) (*Secret, error) {
|
||||
r := c.c.NewRequest("DELETE", "/v1/"+path)
|
||||
|
||||
var values url.Values
|
||||
for k, v := range data {
|
||||
if values == nil {
|
||||
values = make(url.Values)
|
||||
}
|
||||
for _, val := range v {
|
||||
values.Add(k, val)
|
||||
}
|
||||
}
|
||||
|
||||
if values != nil {
|
||||
r.Params = values
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if resp != nil && resp.StatusCode == 404 {
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
switch parseErr {
|
||||
case nil:
|
||||
case io.EOF:
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if secret != nil && (len(secret.Warnings) > 0 || len(secret.Data) > 0) {
|
||||
return secret, err
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Logical) Unwrap(wrappingToken string) (*Secret, error) {
|
||||
var data map[string]interface{}
|
||||
if wrappingToken != "" {
|
||||
if c.c.Token() == "" {
|
||||
c.c.SetToken(wrappingToken)
|
||||
} else if wrappingToken != c.c.Token() {
|
||||
data = map[string]interface{}{
|
||||
"token": wrappingToken,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/wrapping/unwrap")
|
||||
if err := r.SetJSONBody(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
if resp == nil || resp.StatusCode != 404 {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
// In the 404 case this may actually be a wrapped 404 error
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
switch parseErr {
|
||||
case nil:
|
||||
case io.EOF:
|
||||
return nil, nil
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
if secret != nil && (len(secret.Warnings) > 0 || len(secret.Data) > 0) {
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
// Otherwise this might be an old-style wrapping token so attempt the old
|
||||
// method
|
||||
if wrappingToken != "" {
|
||||
origToken := c.c.Token()
|
||||
defer c.c.SetToken(origToken)
|
||||
c.c.SetToken(wrappingToken)
|
||||
}
|
||||
|
||||
secret, err = c.Read(wrappedResponseLocation)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf(fmt.Sprintf("error reading %q: {{err}}", wrappedResponseLocation), err)
|
||||
}
|
||||
if secret == nil {
|
||||
return nil, fmt.Errorf("no value found at %q", wrappedResponseLocation)
|
||||
}
|
||||
if secret.Data == nil {
|
||||
return nil, fmt.Errorf("\"data\" not found in wrapping response")
|
||||
}
|
||||
if _, ok := secret.Data["response"]; !ok {
|
||||
return nil, fmt.Errorf("\"response\" not found in wrapping response \"data\" map")
|
||||
}
|
||||
|
||||
wrappedSecret := new(Secret)
|
||||
buf := bytes.NewBufferString(secret.Data["response"].(string))
|
||||
if err := jsonutil.DecodeJSONFromReader(buf, wrappedSecret); err != nil {
|
||||
return nil, errwrap.Wrapf("error unmarshalling wrapped secret: {{err}}", err)
|
||||
}
|
||||
|
||||
return wrappedSecret, nil
|
||||
}
|
71
vendor/github.com/hashicorp/vault/api/output_string.go
generated
vendored
Normal file
71
vendor/github.com/hashicorp/vault/api/output_string.go
generated
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
)
|
||||
|
||||
const (
|
||||
ErrOutputStringRequest = "output a string, please"
|
||||
)
|
||||
|
||||
var (
|
||||
LastOutputStringError *OutputStringError
|
||||
)
|
||||
|
||||
type OutputStringError struct {
|
||||
*retryablehttp.Request
|
||||
parsingError error
|
||||
parsedCurlString string
|
||||
}
|
||||
|
||||
func (d *OutputStringError) Error() string {
|
||||
if d.parsedCurlString == "" {
|
||||
d.parseRequest()
|
||||
if d.parsingError != nil {
|
||||
return d.parsingError.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return ErrOutputStringRequest
|
||||
}
|
||||
|
||||
func (d *OutputStringError) parseRequest() {
|
||||
body, err := d.Request.BodyBytes()
|
||||
if err != nil {
|
||||
d.parsingError = err
|
||||
return
|
||||
}
|
||||
|
||||
// Build cURL string
|
||||
d.parsedCurlString = "curl "
|
||||
if d.Request.Method != "GET" {
|
||||
d.parsedCurlString = fmt.Sprintf("%s-X %s ", d.parsedCurlString, d.Request.Method)
|
||||
}
|
||||
for k, v := range d.Request.Header {
|
||||
for _, h := range v {
|
||||
if strings.ToLower(k) == "x-vault-token" {
|
||||
h = `$(vault print token)`
|
||||
}
|
||||
d.parsedCurlString = fmt.Sprintf("%s-H \"%s: %s\" ", d.parsedCurlString, k, h)
|
||||
}
|
||||
}
|
||||
|
||||
if len(body) > 0 {
|
||||
// We need to escape single quotes since that's what we're using to
|
||||
// quote the body
|
||||
escapedBody := strings.Replace(string(body), "'", "'\"'\"'", -1)
|
||||
d.parsedCurlString = fmt.Sprintf("%s-d '%s' ", d.parsedCurlString, escapedBody)
|
||||
}
|
||||
|
||||
d.parsedCurlString = fmt.Sprintf("%s%s", d.parsedCurlString, d.Request.URL.String())
|
||||
}
|
||||
|
||||
func (d *OutputStringError) CurlString() string {
|
||||
if d.parsedCurlString == "" {
|
||||
d.parseRequest()
|
||||
}
|
||||
return d.parsedCurlString
|
||||
}
|
189
vendor/github.com/hashicorp/vault/api/plugin_helpers.go
generated
vendored
Normal file
189
vendor/github.com/hashicorp/vault/api/plugin_helpers.go
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"flag"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
squarejwt "gopkg.in/square/go-jose.v2/jwt"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
)
|
||||
|
||||
var (
|
||||
// PluginMetadataModeEnv is an ENV name used to disable TLS communication
|
||||
// to bootstrap mounting plugins.
|
||||
PluginMetadataModeEnv = "VAULT_PLUGIN_METADATA_MODE"
|
||||
|
||||
// PluginUnwrapTokenEnv is the ENV name used to pass unwrap tokens to the
|
||||
// plugin.
|
||||
PluginUnwrapTokenEnv = "VAULT_UNWRAP_TOKEN"
|
||||
)
|
||||
|
||||
// PluginAPIClientMeta is a helper that plugins can use to configure TLS connections
|
||||
// back to Vault.
|
||||
type PluginAPIClientMeta struct {
|
||||
// These are set by the command line flags.
|
||||
flagCACert string
|
||||
flagCAPath string
|
||||
flagClientCert string
|
||||
flagClientKey string
|
||||
flagInsecure bool
|
||||
}
|
||||
|
||||
// FlagSet returns the flag set for configuring the TLS connection
|
||||
func (f *PluginAPIClientMeta) FlagSet() *flag.FlagSet {
|
||||
fs := flag.NewFlagSet("vault plugin settings", flag.ContinueOnError)
|
||||
|
||||
fs.StringVar(&f.flagCACert, "ca-cert", "", "")
|
||||
fs.StringVar(&f.flagCAPath, "ca-path", "", "")
|
||||
fs.StringVar(&f.flagClientCert, "client-cert", "", "")
|
||||
fs.StringVar(&f.flagClientKey, "client-key", "", "")
|
||||
fs.BoolVar(&f.flagInsecure, "tls-skip-verify", false, "")
|
||||
|
||||
return fs
|
||||
}
|
||||
|
||||
// GetTLSConfig will return a TLSConfig based off the values from the flags
|
||||
func (f *PluginAPIClientMeta) GetTLSConfig() *TLSConfig {
|
||||
// If we need custom TLS configuration, then set it
|
||||
if f.flagCACert != "" || f.flagCAPath != "" || f.flagClientCert != "" || f.flagClientKey != "" || f.flagInsecure {
|
||||
t := &TLSConfig{
|
||||
CACert: f.flagCACert,
|
||||
CAPath: f.flagCAPath,
|
||||
ClientCert: f.flagClientCert,
|
||||
ClientKey: f.flagClientKey,
|
||||
TLSServerName: "",
|
||||
Insecure: f.flagInsecure,
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VaultPluginTLSProvider is run inside a plugin and retrieves the response
|
||||
// wrapped TLS certificate from vault. It returns a configured TLS Config.
|
||||
func VaultPluginTLSProvider(apiTLSConfig *TLSConfig) func() (*tls.Config, error) {
|
||||
if os.Getenv(PluginMetadataModeEnv) == "true" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return func() (*tls.Config, error) {
|
||||
unwrapToken := os.Getenv(PluginUnwrapTokenEnv)
|
||||
|
||||
parsedJWT, err := squarejwt.ParseSigned(unwrapToken)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing wrapping token: {{err}}", err)
|
||||
}
|
||||
|
||||
var allClaims = make(map[string]interface{})
|
||||
if err = parsedJWT.UnsafeClaimsWithoutVerification(&allClaims); err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing claims from wrapping token: {{err}}", err)
|
||||
}
|
||||
|
||||
addrClaimRaw, ok := allClaims["addr"]
|
||||
if !ok {
|
||||
return nil, errors.New("could not validate addr claim")
|
||||
}
|
||||
vaultAddr, ok := addrClaimRaw.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("could not parse addr claim")
|
||||
}
|
||||
if vaultAddr == "" {
|
||||
return nil, errors.New(`no vault api_addr found`)
|
||||
}
|
||||
|
||||
// Sanity check the value
|
||||
if _, err := url.Parse(vaultAddr); err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing the vault api_addr: {{err}}", err)
|
||||
}
|
||||
|
||||
// Unwrap the token
|
||||
clientConf := DefaultConfig()
|
||||
clientConf.Address = vaultAddr
|
||||
if apiTLSConfig != nil {
|
||||
err := clientConf.ConfigureTLS(apiTLSConfig)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error configuring api client {{err}}", err)
|
||||
}
|
||||
}
|
||||
client, err := NewClient(clientConf)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error during api client creation: {{err}}", err)
|
||||
}
|
||||
|
||||
// Reset token value to make sure nothing has been set by default
|
||||
client.ClearToken()
|
||||
|
||||
secret, err := client.Logical().Unwrap(unwrapToken)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error during token unwrap request: {{err}}", err)
|
||||
}
|
||||
if secret == nil {
|
||||
return nil, errors.New("error during token unwrap request: secret is nil")
|
||||
}
|
||||
|
||||
// Retrieve and parse the server's certificate
|
||||
serverCertBytesRaw, ok := secret.Data["ServerCert"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("error unmarshalling certificate")
|
||||
}
|
||||
|
||||
serverCertBytes, err := base64.StdEncoding.DecodeString(serverCertBytesRaw)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing certificate: {{err}}", err)
|
||||
}
|
||||
|
||||
serverCert, err := x509.ParseCertificate(serverCertBytes)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing certificate: {{err}}", err)
|
||||
}
|
||||
|
||||
// Retrieve and parse the server's private key
|
||||
serverKeyB64, ok := secret.Data["ServerKey"].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("error unmarshalling certificate")
|
||||
}
|
||||
|
||||
serverKeyRaw, err := base64.StdEncoding.DecodeString(serverKeyB64)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing certificate: {{err}}", err)
|
||||
}
|
||||
|
||||
serverKey, err := x509.ParseECPrivateKey(serverKeyRaw)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing certificate: {{err}}", err)
|
||||
}
|
||||
|
||||
// Add CA cert to the cert pool
|
||||
caCertPool := x509.NewCertPool()
|
||||
caCertPool.AddCert(serverCert)
|
||||
|
||||
// Build a certificate object out of the server's cert and private key.
|
||||
cert := tls.Certificate{
|
||||
Certificate: [][]byte{serverCertBytes},
|
||||
PrivateKey: serverKey,
|
||||
Leaf: serverCert,
|
||||
}
|
||||
|
||||
// Setup TLS config
|
||||
tlsConfig := &tls.Config{
|
||||
ClientCAs: caCertPool,
|
||||
RootCAs: caCertPool,
|
||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||
// TLS 1.2 minimum
|
||||
MinVersion: tls.VersionTLS12,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ServerName: serverCert.Subject.CommonName,
|
||||
}
|
||||
tlsConfig.BuildNameToCertificate()
|
||||
|
||||
return tlsConfig, nil
|
||||
}
|
||||
}
|
148
vendor/github.com/hashicorp/vault/api/request.go
generated
vendored
Normal file
148
vendor/github.com/hashicorp/vault/api/request.go
generated
vendored
Normal file
@ -0,0 +1,148 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
)
|
||||
|
||||
// Request is a raw request configuration structure used to initiate
|
||||
// API requests to the Vault server.
|
||||
type Request struct {
|
||||
Method string
|
||||
URL *url.URL
|
||||
Host string
|
||||
Params url.Values
|
||||
Headers http.Header
|
||||
ClientToken string
|
||||
MFAHeaderVals []string
|
||||
WrapTTL string
|
||||
Obj interface{}
|
||||
|
||||
// When possible, use BodyBytes as it is more efficient due to how the
|
||||
// retry logic works
|
||||
BodyBytes []byte
|
||||
|
||||
// Fallback
|
||||
Body io.Reader
|
||||
BodySize int64
|
||||
|
||||
// Whether to request overriding soft-mandatory Sentinel policies (RGPs and
|
||||
// EGPs). If set, the override flag will take effect for all policies
|
||||
// evaluated during the request.
|
||||
PolicyOverride bool
|
||||
}
|
||||
|
||||
// SetJSONBody is used to set a request body that is a JSON-encoded value.
|
||||
func (r *Request) SetJSONBody(val interface{}) error {
|
||||
buf, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Obj = val
|
||||
r.BodyBytes = buf
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResetJSONBody is used to reset the body for a redirect
|
||||
func (r *Request) ResetJSONBody() error {
|
||||
if r.BodyBytes == nil {
|
||||
return nil
|
||||
}
|
||||
return r.SetJSONBody(r.Obj)
|
||||
}
|
||||
|
||||
// DEPRECATED: ToHTTP turns this request into a valid *http.Request for use
|
||||
// with the net/http package.
|
||||
func (r *Request) ToHTTP() (*http.Request, error) {
|
||||
req, err := r.toRetryableHTTP()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case r.BodyBytes == nil && r.Body == nil:
|
||||
// No body
|
||||
|
||||
case r.BodyBytes != nil:
|
||||
req.Request.Body = ioutil.NopCloser(bytes.NewReader(r.BodyBytes))
|
||||
|
||||
default:
|
||||
if c, ok := r.Body.(io.ReadCloser); ok {
|
||||
req.Request.Body = c
|
||||
} else {
|
||||
req.Request.Body = ioutil.NopCloser(r.Body)
|
||||
}
|
||||
}
|
||||
|
||||
return req.Request, nil
|
||||
}
|
||||
|
||||
func (r *Request) toRetryableHTTP() (*retryablehttp.Request, error) {
|
||||
// Encode the query parameters
|
||||
r.URL.RawQuery = r.Params.Encode()
|
||||
|
||||
// Create the HTTP request, defaulting to retryable
|
||||
var req *retryablehttp.Request
|
||||
|
||||
var err error
|
||||
var body interface{}
|
||||
|
||||
switch {
|
||||
case r.BodyBytes == nil && r.Body == nil:
|
||||
// No body
|
||||
|
||||
case r.BodyBytes != nil:
|
||||
// Use bytes, it's more efficient
|
||||
body = r.BodyBytes
|
||||
|
||||
default:
|
||||
body = r.Body
|
||||
}
|
||||
|
||||
req, err = retryablehttp.NewRequest(r.Method, r.URL.RequestURI(), body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.URL.User = r.URL.User
|
||||
req.URL.Scheme = r.URL.Scheme
|
||||
req.URL.Host = r.URL.Host
|
||||
req.Host = r.Host
|
||||
|
||||
if r.Headers != nil {
|
||||
for header, vals := range r.Headers {
|
||||
for _, val := range vals {
|
||||
req.Header.Add(header, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ClientToken) != 0 {
|
||||
req.Header.Set(consts.AuthHeaderName, r.ClientToken)
|
||||
}
|
||||
|
||||
if len(r.WrapTTL) != 0 {
|
||||
req.Header.Set("X-Vault-Wrap-TTL", r.WrapTTL)
|
||||
}
|
||||
|
||||
if len(r.MFAHeaderVals) != 0 {
|
||||
for _, mfaHeaderVal := range r.MFAHeaderVals {
|
||||
req.Header.Add("X-Vault-MFA", mfaHeaderVal)
|
||||
}
|
||||
}
|
||||
|
||||
if r.PolicyOverride {
|
||||
req.Header.Set("X-Vault-Policy-Override", "true")
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
120
vendor/github.com/hashicorp/vault/api/response.go
generated
vendored
Normal file
120
vendor/github.com/hashicorp/vault/api/response.go
generated
vendored
Normal file
@ -0,0 +1,120 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
)
|
||||
|
||||
// Response is a raw response that wraps an HTTP response.
|
||||
type Response struct {
|
||||
*http.Response
|
||||
}
|
||||
|
||||
// DecodeJSON will decode the response body to a JSON structure. This
|
||||
// will consume the response body, but will not close it. Close must
|
||||
// still be called.
|
||||
func (r *Response) DecodeJSON(out interface{}) error {
|
||||
return jsonutil.DecodeJSONFromReader(r.Body, out)
|
||||
}
|
||||
|
||||
// Error returns an error response if there is one. If there is an error,
|
||||
// this will fully consume the response body, but will not close it. The
|
||||
// body must still be closed manually.
|
||||
func (r *Response) Error() error {
|
||||
// 200 to 399 are okay status codes. 429 is the code for health status of
|
||||
// standby nodes, otherwise, 429 is treated as quota limit reached.
|
||||
if (r.StatusCode >= 200 && r.StatusCode < 400) || (r.StatusCode == 429 && r.Request.URL.Path == "/v1/sys/health") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We have an error. Let's copy the body into our own buffer first,
|
||||
// so that if we can't decode JSON, we can at least copy it raw.
|
||||
bodyBuf := &bytes.Buffer{}
|
||||
if _, err := io.Copy(bodyBuf, r.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Body.Close()
|
||||
r.Body = ioutil.NopCloser(bodyBuf)
|
||||
|
||||
// Build up the error object
|
||||
respErr := &ResponseError{
|
||||
HTTPMethod: r.Request.Method,
|
||||
URL: r.Request.URL.String(),
|
||||
StatusCode: r.StatusCode,
|
||||
}
|
||||
|
||||
// Decode the error response if we can. Note that we wrap the bodyBuf
|
||||
// in a bytes.Reader here so that the JSON decoder doesn't move the
|
||||
// read pointer for the original buffer.
|
||||
var resp ErrorResponse
|
||||
if err := jsonutil.DecodeJSON(bodyBuf.Bytes(), &resp); err != nil {
|
||||
// Store the fact that we couldn't decode the errors
|
||||
respErr.RawError = true
|
||||
respErr.Errors = []string{bodyBuf.String()}
|
||||
} else {
|
||||
// Store the decoded errors
|
||||
respErr.Errors = resp.Errors
|
||||
}
|
||||
|
||||
return respErr
|
||||
}
|
||||
|
||||
// ErrorResponse is the raw structure of errors when they're returned by the
|
||||
// HTTP API.
|
||||
type ErrorResponse struct {
|
||||
Errors []string
|
||||
}
|
||||
|
||||
// ResponseError is the error returned when Vault responds with an error or
|
||||
// non-success HTTP status code. If a request to Vault fails because of a
|
||||
// network error a different error message will be returned. ResponseError gives
|
||||
// access to the underlying errors and status code.
|
||||
type ResponseError struct {
|
||||
// HTTPMethod is the HTTP method for the request (PUT, GET, etc).
|
||||
HTTPMethod string
|
||||
|
||||
// URL is the URL of the request.
|
||||
URL string
|
||||
|
||||
// StatusCode is the HTTP status code.
|
||||
StatusCode int
|
||||
|
||||
// RawError marks that the underlying error messages returned by Vault were
|
||||
// not parsable. The Errors slice will contain the raw response body as the
|
||||
// first and only error string if this value is set to true.
|
||||
RawError bool
|
||||
|
||||
// Errors are the underlying errors returned by Vault.
|
||||
Errors []string
|
||||
}
|
||||
|
||||
// Error returns a human-readable error string for the response error.
|
||||
func (r *ResponseError) Error() string {
|
||||
errString := "Errors"
|
||||
if r.RawError {
|
||||
errString = "Raw Message"
|
||||
}
|
||||
|
||||
var errBody bytes.Buffer
|
||||
errBody.WriteString(fmt.Sprintf(
|
||||
"Error making API request.\n\n"+
|
||||
"URL: %s %s\n"+
|
||||
"Code: %d. %s:\n\n",
|
||||
r.HTTPMethod, r.URL, r.StatusCode, errString))
|
||||
|
||||
if r.RawError && len(r.Errors) == 1 {
|
||||
errBody.WriteString(r.Errors[0])
|
||||
} else {
|
||||
for _, err := range r.Errors {
|
||||
errBody.WriteString(fmt.Sprintf("* %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
return errBody.String()
|
||||
}
|
322
vendor/github.com/hashicorp/vault/api/secret.go
generated
vendored
Normal file
322
vendor/github.com/hashicorp/vault/api/secret.go
generated
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
"github.com/hashicorp/vault/sdk/helper/parseutil"
|
||||
)
|
||||
|
||||
// Secret is the structure returned for every secret within Vault.
|
||||
type Secret struct {
|
||||
// The request ID that generated this response
|
||||
RequestID string `json:"request_id"`
|
||||
|
||||
LeaseID string `json:"lease_id"`
|
||||
LeaseDuration int `json:"lease_duration"`
|
||||
Renewable bool `json:"renewable"`
|
||||
|
||||
// Data is the actual contents of the secret. The format of the data
|
||||
// is arbitrary and up to the secret backend.
|
||||
Data map[string]interface{} `json:"data"`
|
||||
|
||||
// Warnings contains any warnings related to the operation. These
|
||||
// are not issues that caused the command to fail, but that the
|
||||
// client should be aware of.
|
||||
Warnings []string `json:"warnings"`
|
||||
|
||||
// Auth, if non-nil, means that there was authentication information
|
||||
// attached to this response.
|
||||
Auth *SecretAuth `json:"auth,omitempty"`
|
||||
|
||||
// WrapInfo, if non-nil, means that the initial response was wrapped in the
|
||||
// cubbyhole of the given token (which has a TTL of the given number of
|
||||
// seconds)
|
||||
WrapInfo *SecretWrapInfo `json:"wrap_info,omitempty"`
|
||||
}
|
||||
|
||||
// TokenID returns the standardized token ID (token) for the given secret.
|
||||
func (s *Secret) TokenID() (string, error) {
|
||||
if s == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && len(s.Auth.ClientToken) > 0 {
|
||||
return s.Auth.ClientToken, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || s.Data["id"] == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
id, ok := s.Data["id"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("token found but in the wrong format")
|
||||
}
|
||||
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// TokenAccessor returns the standardized token accessor for the given secret.
|
||||
// If the secret is nil or does not contain an accessor, this returns the empty
|
||||
// string.
|
||||
func (s *Secret) TokenAccessor() (string, error) {
|
||||
if s == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && len(s.Auth.Accessor) > 0 {
|
||||
return s.Auth.Accessor, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || s.Data["accessor"] == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
accessor, ok := s.Data["accessor"].(string)
|
||||
if !ok {
|
||||
return "", fmt.Errorf("token found but in the wrong format")
|
||||
}
|
||||
|
||||
return accessor, nil
|
||||
}
|
||||
|
||||
// TokenRemainingUses returns the standardized remaining uses for the given
|
||||
// secret. If the secret is nil or does not contain the "num_uses", this
|
||||
// returns -1. On error, this will return -1 and a non-nil error.
|
||||
func (s *Secret) TokenRemainingUses() (int, error) {
|
||||
if s == nil || s.Data == nil || s.Data["num_uses"] == nil {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
uses, err := parseutil.ParseInt(s.Data["num_uses"])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return int(uses), nil
|
||||
}
|
||||
|
||||
// TokenPolicies returns the standardized list of policies for the given secret.
|
||||
// If the secret is nil or does not contain any policies, this returns nil. It
|
||||
// also populates the secret's Auth info with identity/token policy info.
|
||||
func (s *Secret) TokenPolicies() ([]string, error) {
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && len(s.Auth.Policies) > 0 {
|
||||
return s.Auth.Policies, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || s.Data["policies"] == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var tokenPolicies []string
|
||||
|
||||
// Token policies
|
||||
{
|
||||
_, ok := s.Data["policies"]
|
||||
if !ok {
|
||||
goto TOKEN_DONE
|
||||
}
|
||||
|
||||
sList, ok := s.Data["policies"].([]string)
|
||||
if ok {
|
||||
tokenPolicies = sList
|
||||
goto TOKEN_DONE
|
||||
}
|
||||
|
||||
list, ok := s.Data["policies"].([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert token policies to expected format")
|
||||
}
|
||||
for _, v := range list {
|
||||
p, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert policy %v to string", v)
|
||||
}
|
||||
tokenPolicies = append(tokenPolicies, p)
|
||||
}
|
||||
}
|
||||
|
||||
TOKEN_DONE:
|
||||
var identityPolicies []string
|
||||
|
||||
// Identity policies
|
||||
{
|
||||
_, ok := s.Data["identity_policies"]
|
||||
if !ok {
|
||||
goto DONE
|
||||
}
|
||||
|
||||
sList, ok := s.Data["identity_policies"].([]string)
|
||||
if ok {
|
||||
identityPolicies = sList
|
||||
goto DONE
|
||||
}
|
||||
|
||||
list, ok := s.Data["identity_policies"].([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert identity policies to expected format")
|
||||
}
|
||||
for _, v := range list {
|
||||
p, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert policy %v to string", v)
|
||||
}
|
||||
identityPolicies = append(identityPolicies, p)
|
||||
}
|
||||
}
|
||||
|
||||
DONE:
|
||||
|
||||
if s.Auth == nil {
|
||||
s.Auth = &SecretAuth{}
|
||||
}
|
||||
|
||||
policies := append(tokenPolicies, identityPolicies...)
|
||||
|
||||
s.Auth.TokenPolicies = tokenPolicies
|
||||
s.Auth.IdentityPolicies = identityPolicies
|
||||
s.Auth.Policies = policies
|
||||
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
// TokenMetadata returns the map of metadata associated with this token, if any
|
||||
// exists. If the secret is nil or does not contain the "metadata" key, this
|
||||
// returns nil.
|
||||
func (s *Secret) TokenMetadata() (map[string]string, error) {
|
||||
if s == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && len(s.Auth.Metadata) > 0 {
|
||||
return s.Auth.Metadata, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || (s.Data["metadata"] == nil && s.Data["meta"] == nil) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
data, ok := s.Data["metadata"].(map[string]interface{})
|
||||
if !ok {
|
||||
data, ok = s.Data["meta"].(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert metadata field to expected format")
|
||||
}
|
||||
}
|
||||
|
||||
metadata := make(map[string]string, len(data))
|
||||
for k, v := range data {
|
||||
typed, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to convert metadata value %v to string", v)
|
||||
}
|
||||
metadata[k] = typed
|
||||
}
|
||||
|
||||
return metadata, nil
|
||||
}
|
||||
|
||||
// TokenIsRenewable returns the standardized token renewability for the given
|
||||
// secret. If the secret is nil or does not contain the "renewable" key, this
|
||||
// returns false.
|
||||
func (s *Secret) TokenIsRenewable() (bool, error) {
|
||||
if s == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && s.Auth.Renewable {
|
||||
return s.Auth.Renewable, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || s.Data["renewable"] == nil {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
renewable, err := parseutil.ParseBool(s.Data["renewable"])
|
||||
if err != nil {
|
||||
return false, errwrap.Wrapf("could not convert renewable value to a boolean: {{err}}", err)
|
||||
}
|
||||
|
||||
return renewable, nil
|
||||
}
|
||||
|
||||
// TokenTTL returns the standardized remaining token TTL for the given secret.
|
||||
// If the secret is nil or does not contain a TTL, this returns 0.
|
||||
func (s *Secret) TokenTTL() (time.Duration, error) {
|
||||
if s == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if s.Auth != nil && s.Auth.LeaseDuration > 0 {
|
||||
return time.Duration(s.Auth.LeaseDuration) * time.Second, nil
|
||||
}
|
||||
|
||||
if s.Data == nil || s.Data["ttl"] == nil {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
ttl, err := parseutil.ParseDurationSecond(s.Data["ttl"])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return ttl, nil
|
||||
}
|
||||
|
||||
// SecretWrapInfo contains wrapping information if we have it. If what is
|
||||
// contained is an authentication token, the accessor for the token will be
|
||||
// available in WrappedAccessor.
|
||||
type SecretWrapInfo struct {
|
||||
Token string `json:"token"`
|
||||
Accessor string `json:"accessor"`
|
||||
TTL int `json:"ttl"`
|
||||
CreationTime time.Time `json:"creation_time"`
|
||||
CreationPath string `json:"creation_path"`
|
||||
WrappedAccessor string `json:"wrapped_accessor"`
|
||||
}
|
||||
|
||||
// SecretAuth is the structure containing auth information if we have it.
|
||||
type SecretAuth struct {
|
||||
ClientToken string `json:"client_token"`
|
||||
Accessor string `json:"accessor"`
|
||||
Policies []string `json:"policies"`
|
||||
TokenPolicies []string `json:"token_policies"`
|
||||
IdentityPolicies []string `json:"identity_policies"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
Orphan bool `json:"orphan"`
|
||||
EntityID string `json:"entity_id"`
|
||||
|
||||
LeaseDuration int `json:"lease_duration"`
|
||||
Renewable bool `json:"renewable"`
|
||||
}
|
||||
|
||||
// ParseSecret is used to parse a secret value from JSON from an io.Reader.
|
||||
func ParseSecret(r io.Reader) (*Secret, error) {
|
||||
// First read the data into a buffer. Not super efficient but we want to
|
||||
// know if we actually have a body or not.
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.ReadFrom(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if buf.Len() == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// First decode the JSON into a map[string]interface{}
|
||||
var secret Secret
|
||||
if err := jsonutil.DecodeJSONFromReader(&buf, &secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &secret, nil
|
||||
}
|
62
vendor/github.com/hashicorp/vault/api/ssh.go
generated
vendored
Normal file
62
vendor/github.com/hashicorp/vault/api/ssh.go
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// SSH is used to return a client to invoke operations on SSH backend.
|
||||
type SSH struct {
|
||||
c *Client
|
||||
MountPoint string
|
||||
}
|
||||
|
||||
// SSH returns the client for logical-backend API calls.
|
||||
func (c *Client) SSH() *SSH {
|
||||
return c.SSHWithMountPoint(SSHHelperDefaultMountPoint)
|
||||
}
|
||||
|
||||
// SSHWithMountPoint returns the client with specific SSH mount point.
|
||||
func (c *Client) SSHWithMountPoint(mountPoint string) *SSH {
|
||||
return &SSH{
|
||||
c: c,
|
||||
MountPoint: mountPoint,
|
||||
}
|
||||
}
|
||||
|
||||
// Credential invokes the SSH backend API to create a credential to establish an SSH session.
|
||||
func (c *SSH) Credential(role string, data map[string]interface{}) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/%s/creds/%s", c.MountPoint, role))
|
||||
if err := r.SetJSONBody(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
// SignKey signs the given public key and returns a signed public key to pass
|
||||
// along with the SSH request.
|
||||
func (c *SSH) SignKey(role string, data map[string]interface{}) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/%s/sign/%s", c.MountPoint, role))
|
||||
if err := r.SetJSONBody(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
241
vendor/github.com/hashicorp/vault/api/ssh_agent.go
generated
vendored
Normal file
241
vendor/github.com/hashicorp/vault/api/ssh_agent.go
generated
vendored
Normal file
@ -0,0 +1,241 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
rootcerts "github.com/hashicorp/go-rootcerts"
|
||||
"github.com/hashicorp/hcl"
|
||||
"github.com/hashicorp/hcl/hcl/ast"
|
||||
"github.com/hashicorp/vault/sdk/helper/hclutil"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
const (
|
||||
// SSHHelperDefaultMountPoint is the default path at which SSH backend will be
|
||||
// mounted in the Vault server.
|
||||
SSHHelperDefaultMountPoint = "ssh"
|
||||
|
||||
// VerifyEchoRequest is the echo request message sent as OTP by the helper.
|
||||
VerifyEchoRequest = "verify-echo-request"
|
||||
|
||||
// VerifyEchoResponse is the echo response message sent as a response to OTP
|
||||
// matching echo request.
|
||||
VerifyEchoResponse = "verify-echo-response"
|
||||
)
|
||||
|
||||
// SSHHelper is a structure representing a vault-ssh-helper which can talk to vault server
|
||||
// in order to verify the OTP entered by the user. It contains the path at which
|
||||
// SSH backend is mounted at the server.
|
||||
type SSHHelper struct {
|
||||
c *Client
|
||||
MountPoint string
|
||||
}
|
||||
|
||||
// SSHVerifyResponse is a structure representing the fields in Vault server's
|
||||
// response.
|
||||
type SSHVerifyResponse struct {
|
||||
// Usually empty. If the request OTP is echo request message, this will
|
||||
// be set to the corresponding echo response message.
|
||||
Message string `json:"message" mapstructure:"message"`
|
||||
|
||||
// Username associated with the OTP
|
||||
Username string `json:"username" mapstructure:"username"`
|
||||
|
||||
// IP associated with the OTP
|
||||
IP string `json:"ip" mapstructure:"ip"`
|
||||
|
||||
// Name of the role against which the OTP was issued
|
||||
RoleName string `json:"role_name" mapstructure:"role_name"`
|
||||
}
|
||||
|
||||
// SSHHelperConfig is a structure which represents the entries from the vault-ssh-helper's configuration file.
|
||||
type SSHHelperConfig struct {
|
||||
VaultAddr string `hcl:"vault_addr"`
|
||||
SSHMountPoint string `hcl:"ssh_mount_point"`
|
||||
Namespace string `hcl:"namespace"`
|
||||
CACert string `hcl:"ca_cert"`
|
||||
CAPath string `hcl:"ca_path"`
|
||||
AllowedCidrList string `hcl:"allowed_cidr_list"`
|
||||
AllowedRoles string `hcl:"allowed_roles"`
|
||||
TLSSkipVerify bool `hcl:"tls_skip_verify"`
|
||||
TLSServerName string `hcl:"tls_server_name"`
|
||||
}
|
||||
|
||||
// SetTLSParameters sets the TLS parameters for this SSH agent.
|
||||
func (c *SSHHelperConfig) SetTLSParameters(clientConfig *Config, certPool *x509.CertPool) {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: c.TLSSkipVerify,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
RootCAs: certPool,
|
||||
ServerName: c.TLSServerName,
|
||||
}
|
||||
|
||||
transport := cleanhttp.DefaultTransport()
|
||||
transport.TLSClientConfig = tlsConfig
|
||||
clientConfig.HttpClient.Transport = transport
|
||||
}
|
||||
|
||||
// Returns true if any of the following conditions are true:
|
||||
// * CA cert is configured
|
||||
// * CA path is configured
|
||||
// * configured to skip certificate verification
|
||||
// * TLS server name is configured
|
||||
//
|
||||
func (c *SSHHelperConfig) shouldSetTLSParameters() bool {
|
||||
return c.CACert != "" || c.CAPath != "" || c.TLSServerName != "" || c.TLSSkipVerify
|
||||
}
|
||||
|
||||
// NewClient returns a new client for the configuration. This client will be used by the
|
||||
// vault-ssh-helper to communicate with Vault server and verify the OTP entered by user.
|
||||
// If the configuration supplies Vault SSL certificates, then the client will
|
||||
// have TLS configured in its transport.
|
||||
func (c *SSHHelperConfig) NewClient() (*Client, error) {
|
||||
// Creating a default client configuration for communicating with vault server.
|
||||
clientConfig := DefaultConfig()
|
||||
|
||||
// Pointing the client to the actual address of vault server.
|
||||
clientConfig.Address = c.VaultAddr
|
||||
|
||||
// Check if certificates are provided via config file.
|
||||
if c.shouldSetTLSParameters() {
|
||||
rootConfig := &rootcerts.Config{
|
||||
CAFile: c.CACert,
|
||||
CAPath: c.CAPath,
|
||||
}
|
||||
certPool, err := rootcerts.LoadCACerts(rootConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Enable TLS on the HTTP client information
|
||||
c.SetTLSParameters(clientConfig, certPool)
|
||||
}
|
||||
|
||||
// Creating the client object for the given configuration
|
||||
client, err := NewClient(clientConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Configure namespace
|
||||
if c.Namespace != "" {
|
||||
client.SetNamespace(c.Namespace)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// LoadSSHHelperConfig loads ssh-helper's configuration from the file and populates the corresponding
|
||||
// in-memory structure.
|
||||
//
|
||||
// Vault address is a required parameter.
|
||||
// Mount point defaults to "ssh".
|
||||
func LoadSSHHelperConfig(path string) (*SSHHelperConfig, error) {
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
||||
}
|
||||
return ParseSSHHelperConfig(string(contents))
|
||||
}
|
||||
|
||||
// ParseSSHHelperConfig parses the given contents as a string for the SSHHelper
|
||||
// configuration.
|
||||
func ParseSSHHelperConfig(contents string) (*SSHHelperConfig, error) {
|
||||
root, err := hcl.Parse(string(contents))
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error parsing config: {{err}}", err)
|
||||
}
|
||||
|
||||
list, ok := root.Node.(*ast.ObjectList)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error parsing config: file doesn't contain a root object")
|
||||
}
|
||||
|
||||
valid := []string{
|
||||
"vault_addr",
|
||||
"ssh_mount_point",
|
||||
"namespace",
|
||||
"ca_cert",
|
||||
"ca_path",
|
||||
"allowed_cidr_list",
|
||||
"allowed_roles",
|
||||
"tls_skip_verify",
|
||||
"tls_server_name",
|
||||
}
|
||||
if err := hclutil.CheckHCLKeys(list, valid); err != nil {
|
||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
||||
}
|
||||
|
||||
var c SSHHelperConfig
|
||||
c.SSHMountPoint = SSHHelperDefaultMountPoint
|
||||
if err := hcl.DecodeObject(&c, list); err != nil {
|
||||
return nil, multierror.Prefix(err, "ssh_helper:")
|
||||
}
|
||||
|
||||
if c.VaultAddr == "" {
|
||||
return nil, fmt.Errorf(`missing config "vault_addr"`)
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// SSHHelper creates an SSHHelper object which can talk to Vault server with SSH backend
|
||||
// mounted at default path ("ssh").
|
||||
func (c *Client) SSHHelper() *SSHHelper {
|
||||
return c.SSHHelperWithMountPoint(SSHHelperDefaultMountPoint)
|
||||
}
|
||||
|
||||
// SSHHelperWithMountPoint creates an SSHHelper object which can talk to Vault server with SSH backend
|
||||
// mounted at a specific mount point.
|
||||
func (c *Client) SSHHelperWithMountPoint(mountPoint string) *SSHHelper {
|
||||
return &SSHHelper{
|
||||
c: c,
|
||||
MountPoint: mountPoint,
|
||||
}
|
||||
}
|
||||
|
||||
// Verify verifies if the key provided by user is present in Vault server. The response
|
||||
// will contain the IP address and username associated with the OTP. In case the
|
||||
// OTP matches the echo request message, instead of searching an entry for the OTP,
|
||||
// an echo response message is returned. This feature is used by ssh-helper to verify if
|
||||
// its configured correctly.
|
||||
func (c *SSHHelper) Verify(otp string) (*SSHVerifyResponse, error) {
|
||||
data := map[string]interface{}{
|
||||
"otp": otp,
|
||||
}
|
||||
verifyPath := fmt.Sprintf("/v1/%s/verify", c.MountPoint)
|
||||
r := c.c.NewRequest("PUT", verifyPath)
|
||||
if err := r.SetJSONBody(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if secret.Data == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var verifyResp SSHVerifyResponse
|
||||
err = mapstructure.Decode(secret.Data, &verifyResp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &verifyResp, nil
|
||||
}
|
11
vendor/github.com/hashicorp/vault/api/sys.go
generated
vendored
Normal file
11
vendor/github.com/hashicorp/vault/api/sys.go
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
package api
|
||||
|
||||
// Sys is used to perform system-related operations on Vault.
|
||||
type Sys struct {
|
||||
c *Client
|
||||
}
|
||||
|
||||
// Sys is used to return the client for sys-related API calls.
|
||||
func (c *Client) Sys() *Sys {
|
||||
return &Sys{c: c}
|
||||
}
|
136
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
Normal file
136
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) AuditHash(path string, input string) (string, error) {
|
||||
body := map[string]interface{}{
|
||||
"input": input,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit-hash/%s", path))
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return "", errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
hash, ok := secret.Data["hash"]
|
||||
if !ok {
|
||||
return "", errors.New("hash not found in response data")
|
||||
}
|
||||
hashStr, ok := hash.(string)
|
||||
if !ok {
|
||||
return "", errors.New("could not parse hash in response data")
|
||||
}
|
||||
|
||||
return hashStr, nil
|
||||
}
|
||||
|
||||
func (c *Sys) ListAudit() (map[string]*Audit, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/audit")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
mounts := map[string]*Audit{}
|
||||
err = mapstructure.Decode(secret.Data, &mounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
// DEPRECATED: Use EnableAuditWithOptions instead
|
||||
func (c *Sys) EnableAudit(
|
||||
path string, auditType string, desc string, opts map[string]string) error {
|
||||
return c.EnableAuditWithOptions(path, &EnableAuditOptions{
|
||||
Type: auditType,
|
||||
Description: desc,
|
||||
Options: opts,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Sys) EnableAuditWithOptions(path string, options *EnableAuditOptions) error {
|
||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit/%s", path))
|
||||
if err := r.SetJSONBody(options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Sys) DisableAudit(path string) error {
|
||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/audit/%s", path))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Structures for the requests/response are all down here. They aren't
|
||||
// individually documented because the map almost directly to the raw HTTP API
|
||||
// documentation. Please refer to that documentation for more details.
|
||||
|
||||
type EnableAuditOptions struct {
|
||||
Type string `json:"type" mapstructure:"type"`
|
||||
Description string `json:"description" mapstructure:"description"`
|
||||
Options map[string]string `json:"options" mapstructure:"options"`
|
||||
Local bool `json:"local" mapstructure:"local"`
|
||||
}
|
||||
|
||||
type Audit struct {
|
||||
Type string `json:"type" mapstructure:"type"`
|
||||
Description string `json:"description" mapstructure:"description"`
|
||||
Options map[string]string `json:"options" mapstructure:"options"`
|
||||
Local bool `json:"local" mapstructure:"local"`
|
||||
Path string `json:"path" mapstructure:"path"`
|
||||
}
|
80
vendor/github.com/hashicorp/vault/api/sys_auth.go
generated
vendored
Normal file
80
vendor/github.com/hashicorp/vault/api/sys_auth.go
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) ListAuth() (map[string]*AuthMount, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/auth")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
mounts := map[string]*AuthMount{}
|
||||
err = mapstructure.Decode(secret.Data, &mounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
// DEPRECATED: Use EnableAuthWithOptions instead
|
||||
func (c *Sys) EnableAuth(path, authType, desc string) error {
|
||||
return c.EnableAuthWithOptions(path, &EnableAuthOptions{
|
||||
Type: authType,
|
||||
Description: desc,
|
||||
})
|
||||
}
|
||||
|
||||
func (c *Sys) EnableAuthWithOptions(path string, options *EnableAuthOptions) error {
|
||||
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/auth/%s", path))
|
||||
if err := r.SetJSONBody(options); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Sys) DisableAuth(path string) error {
|
||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/auth/%s", path))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Rather than duplicate, we can use modern Go's type aliasing
|
||||
type EnableAuthOptions = MountInput
|
||||
type AuthConfigInput = MountConfigInput
|
||||
type AuthMount = MountOutput
|
||||
type AuthConfigOutput = MountConfigOutput
|
64
vendor/github.com/hashicorp/vault/api/sys_capabilities.go
generated
vendored
Normal file
64
vendor/github.com/hashicorp/vault/api/sys_capabilities.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) CapabilitiesSelf(path string) ([]string, error) {
|
||||
return c.Capabilities(c.c.Token(), path)
|
||||
}
|
||||
|
||||
func (c *Sys) Capabilities(token, path string) ([]string, error) {
|
||||
body := map[string]string{
|
||||
"token": token,
|
||||
"path": path,
|
||||
}
|
||||
|
||||
reqPath := "/v1/sys/capabilities"
|
||||
if token == c.c.Token() {
|
||||
reqPath = fmt.Sprintf("%s-self", reqPath)
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("POST", reqPath)
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var res []string
|
||||
err = mapstructure.Decode(secret.Data[path], &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(res) == 0 {
|
||||
_, ok := secret.Data["capabilities"]
|
||||
if ok {
|
||||
err = mapstructure.Decode(secret.Data["capabilities"], &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
105
vendor/github.com/hashicorp/vault/api/sys_config_cors.go
generated
vendored
Normal file
105
vendor/github.com/hashicorp/vault/api/sys_config_cors.go
generated
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) CORSStatus() (*CORSResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/config/cors")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result CORSResponse
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) ConfigureCORS(req *CORSRequest) (*CORSResponse, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/config/cors")
|
||||
if err := r.SetJSONBody(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result CORSResponse
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) DisableCORS() (*CORSResponse, error) {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/config/cors")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result CORSResponse
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type CORSRequest struct {
|
||||
AllowedOrigins string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
}
|
||||
|
||||
type CORSResponse struct {
|
||||
AllowedOrigins string `json:"allowed_origins" mapstructure:"allowed_origins"`
|
||||
Enabled bool `json:"enabled" mapstructure:"enabled"`
|
||||
}
|
140
vendor/github.com/hashicorp/vault/api/sys_generate_root.go
generated
vendored
Normal file
140
vendor/github.com/hashicorp/vault/api/sys_generate_root.go
generated
vendored
Normal file
@ -0,0 +1,140 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) GenerateRootStatus() (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootStatusCommon("/v1/sys/generate-root/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateDROperationTokenStatus() (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootStatusCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRecoveryOperationTokenStatus() (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootStatusCommon("/v1/sys/generate-recovery-token/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) generateRootStatusCommon(path string) (*GenerateRootStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", path)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result GenerateRootStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRootInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootInitCommon("/v1/sys/generate-root/attempt", otp, pgpKey)
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateDROperationTokenInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootInitCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt", otp, pgpKey)
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRecoveryOperationTokenInit(otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootInitCommon("/v1/sys/generate-recovery-token/attempt", otp, pgpKey)
|
||||
}
|
||||
|
||||
func (c *Sys) generateRootInitCommon(path, otp, pgpKey string) (*GenerateRootStatusResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"otp": otp,
|
||||
"pgp_key": pgpKey,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", path)
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result GenerateRootStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRootCancel() error {
|
||||
return c.generateRootCancelCommon("/v1/sys/generate-root/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateDROperationTokenCancel() error {
|
||||
return c.generateRootCancelCommon("/v1/sys/replication/dr/secondary/generate-operation-token/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRecoveryOperationTokenCancel() error {
|
||||
return c.generateRootCancelCommon("/v1/sys/generate-recovery-token/attempt")
|
||||
}
|
||||
|
||||
func (c *Sys) generateRootCancelCommon(path string) error {
|
||||
r := c.c.NewRequest("DELETE", path)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRootUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootUpdateCommon("/v1/sys/generate-root/update", shard, nonce)
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateDROperationTokenUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootUpdateCommon("/v1/sys/replication/dr/secondary/generate-operation-token/update", shard, nonce)
|
||||
}
|
||||
|
||||
func (c *Sys) GenerateRecoveryOperationTokenUpdate(shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||
return c.generateRootUpdateCommon("/v1/sys/generate-recovery-token/update", shard, nonce)
|
||||
}
|
||||
|
||||
func (c *Sys) generateRootUpdateCommon(path, shard, nonce string) (*GenerateRootStatusResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"key": shard,
|
||||
"nonce": nonce,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", path)
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result GenerateRootStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type GenerateRootStatusResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Started bool `json:"started"`
|
||||
Progress int `json:"progress"`
|
||||
Required int `json:"required"`
|
||||
Complete bool `json:"complete"`
|
||||
EncodedToken string `json:"encoded_token"`
|
||||
EncodedRootToken string `json:"encoded_root_token"`
|
||||
PGPFingerprint string `json:"pgp_fingerprint"`
|
||||
OTP string `json:"otp"`
|
||||
OTPLength int `json:"otp_length"`
|
||||
}
|
41
vendor/github.com/hashicorp/vault/api/sys_health.go
generated
vendored
Normal file
41
vendor/github.com/hashicorp/vault/api/sys_health.go
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) Health() (*HealthResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/health")
|
||||
// If the code is 400 or above it will automatically turn into an error,
|
||||
// but the sys/health API defaults to returning 5xx when not sealed or
|
||||
// inited, so we force this code to be something else so we parse correctly
|
||||
r.Params.Add("uninitcode", "299")
|
||||
r.Params.Add("sealedcode", "299")
|
||||
r.Params.Add("standbycode", "299")
|
||||
r.Params.Add("drsecondarycode", "299")
|
||||
r.Params.Add("performancestandbycode", "299")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result HealthResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type HealthResponse struct {
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
Standby bool `json:"standby"`
|
||||
PerformanceStandby bool `json:"performance_standby"`
|
||||
ReplicationPerformanceMode string `json:"replication_performance_mode"`
|
||||
ReplicationDRMode string `json:"replication_dr_mode"`
|
||||
ServerTimeUTC int64 `json:"server_time_utc"`
|
||||
Version string `json:"version"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
LastWAL uint64 `json:"last_wal,omitempty"`
|
||||
}
|
61
vendor/github.com/hashicorp/vault/api/sys_init.go
generated
vendored
Normal file
61
vendor/github.com/hashicorp/vault/api/sys_init.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) InitStatus() (bool, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/init")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result InitStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return result.Initialized, err
|
||||
}
|
||||
|
||||
func (c *Sys) Init(opts *InitRequest) (*InitResponse, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/init")
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result InitResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type InitRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
StoredShares int `json:"stored_shares"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
RecoveryShares int `json:"recovery_shares"`
|
||||
RecoveryThreshold int `json:"recovery_threshold"`
|
||||
RecoveryPGPKeys []string `json:"recovery_pgp_keys"`
|
||||
RootTokenPGPKey string `json:"root_token_pgp_key"`
|
||||
}
|
||||
|
||||
type InitStatusResponse struct {
|
||||
Initialized bool
|
||||
}
|
||||
|
||||
type InitResponse struct {
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
RecoveryKeys []string `json:"recovery_keys"`
|
||||
RecoveryKeysB64 []string `json:"recovery_keys_base64"`
|
||||
RootToken string `json:"root_token"`
|
||||
}
|
31
vendor/github.com/hashicorp/vault/api/sys_leader.go
generated
vendored
Normal file
31
vendor/github.com/hashicorp/vault/api/sys_leader.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) Leader() (*LeaderResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/leader")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result LeaderResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type LeaderResponse struct {
|
||||
HAEnabled bool `json:"ha_enabled"`
|
||||
IsSelf bool `json:"is_self"`
|
||||
LeaderAddress string `json:"leader_address"`
|
||||
LeaderClusterAddress string `json:"leader_cluster_address"`
|
||||
PerfStandby bool `json:"performance_standby"`
|
||||
PerfStandbyLastRemoteWAL uint64 `json:"performance_standby_last_remote_wal"`
|
||||
LastWAL uint64 `json:"last_wal"`
|
||||
RaftCommittedIndex uint64 `json:"raft_committed_index,omitempty"`
|
||||
RaftAppliedIndex uint64 `json:"raft_applied_index,omitempty"`
|
||||
}
|
111
vendor/github.com/hashicorp/vault/api/sys_leases.go
generated
vendored
Normal file
111
vendor/github.com/hashicorp/vault/api/sys_leases.go
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
func (c *Sys) Renew(id string, increment int) (*Secret, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/renew")
|
||||
|
||||
body := map[string]interface{}{
|
||||
"increment": increment,
|
||||
"lease_id": id,
|
||||
}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return ParseSecret(resp.Body)
|
||||
}
|
||||
|
||||
func (c *Sys) Revoke(id string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke")
|
||||
body := map[string]interface{}{
|
||||
"lease_id": id,
|
||||
}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RevokePrefix(id string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-prefix/"+id)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RevokeForce(id string) error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/leases/revoke-force/"+id)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RevokeWithOptions(opts *RevokeOptions) error {
|
||||
if opts == nil {
|
||||
return errors.New("nil options provided")
|
||||
}
|
||||
|
||||
// Construct path
|
||||
path := "/v1/sys/leases/revoke/"
|
||||
switch {
|
||||
case opts.Force:
|
||||
path = "/v1/sys/leases/revoke-force/"
|
||||
case opts.Prefix:
|
||||
path = "/v1/sys/leases/revoke-prefix/"
|
||||
}
|
||||
path += opts.LeaseID
|
||||
|
||||
r := c.c.NewRequest("PUT", path)
|
||||
if !opts.Force {
|
||||
body := map[string]interface{}{
|
||||
"sync": opts.Sync,
|
||||
}
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type RevokeOptions struct {
|
||||
LeaseID string
|
||||
Force bool
|
||||
Prefix bool
|
||||
Sync bool
|
||||
}
|
64
vendor/github.com/hashicorp/vault/api/sys_monitor.go
generated
vendored
Normal file
64
vendor/github.com/hashicorp/vault/api/sys_monitor.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Monitor returns a channel that outputs strings containing the log messages
|
||||
// coming from the server.
|
||||
func (c *Sys) Monitor(ctx context.Context, logLevel string) (chan string, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/monitor")
|
||||
|
||||
if logLevel == "" {
|
||||
r.Params.Add("log_level", "info")
|
||||
} else {
|
||||
r.Params.Add("log_level", logLevel)
|
||||
}
|
||||
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logCh := make(chan string, 64)
|
||||
|
||||
go func() {
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
droppedCount := 0
|
||||
|
||||
defer close(logCh)
|
||||
defer resp.Body.Close()
|
||||
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !scanner.Scan() {
|
||||
return
|
||||
}
|
||||
|
||||
logMessage := scanner.Text()
|
||||
|
||||
if droppedCount > 0 {
|
||||
select {
|
||||
case logCh <- fmt.Sprintf("Monitor dropped %d logs during monitor request\n", droppedCount):
|
||||
droppedCount = 0
|
||||
default:
|
||||
droppedCount++
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case logCh <- logMessage:
|
||||
default:
|
||||
droppedCount++
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return logCh, nil
|
||||
}
|
187
vendor/github.com/hashicorp/vault/api/sys_mounts.go
generated
vendored
Normal file
187
vendor/github.com/hashicorp/vault/api/sys_mounts.go
generated
vendored
Normal file
@ -0,0 +1,187 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) ListMounts() (map[string]*MountOutput, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/mounts")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
mounts := map[string]*MountOutput{}
|
||||
err = mapstructure.Decode(secret.Data, &mounts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
func (c *Sys) Mount(path string, mountInfo *MountInput) error {
|
||||
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s", path))
|
||||
if err := r.SetJSONBody(mountInfo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Sys) Unmount(path string) error {
|
||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/mounts/%s", path))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) Remount(from, to string) error {
|
||||
body := map[string]interface{}{
|
||||
"from": from,
|
||||
"to": to,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("POST", "/v1/sys/remount")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) TuneMount(path string, config MountConfigInput) error {
|
||||
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
|
||||
if err := r.SetJSONBody(config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) MountConfig(path string) (*MountConfigOutput, error) {
|
||||
r := c.c.NewRequest("GET", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result MountConfigOutput
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type MountInput struct {
|
||||
Type string `json:"type"`
|
||||
Description string `json:"description"`
|
||||
Config MountConfigInput `json:"config"`
|
||||
Local bool `json:"local"`
|
||||
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
|
||||
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
|
||||
Options map[string]string `json:"options"`
|
||||
|
||||
// Deprecated: Newer server responses should be returning this information in the
|
||||
// Type field (json: "type") instead.
|
||||
PluginName string `json:"plugin_name,omitempty"`
|
||||
}
|
||||
|
||||
type MountConfigInput struct {
|
||||
Options map[string]string `json:"options" mapstructure:"options"`
|
||||
DefaultLeaseTTL string `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
||||
Description *string `json:"description,omitempty" mapstructure:"description"`
|
||||
MaxLeaseTTL string `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
||||
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
||||
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
|
||||
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
|
||||
TokenType string `json:"token_type,omitempty" mapstructure:"token_type"`
|
||||
|
||||
// Deprecated: This field will always be blank for newer server responses.
|
||||
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||
}
|
||||
|
||||
type MountOutput struct {
|
||||
UUID string `json:"uuid"`
|
||||
Type string `json:"type"`
|
||||
Description string `json:"description"`
|
||||
Accessor string `json:"accessor"`
|
||||
Config MountConfigOutput `json:"config"`
|
||||
Options map[string]string `json:"options"`
|
||||
Local bool `json:"local"`
|
||||
SealWrap bool `json:"seal_wrap" mapstructure:"seal_wrap"`
|
||||
ExternalEntropyAccess bool `json:"external_entropy_access" mapstructure:"external_entropy_access"`
|
||||
}
|
||||
|
||||
type MountConfigOutput struct {
|
||||
DefaultLeaseTTL int `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
|
||||
MaxLeaseTTL int `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
|
||||
ForceNoCache bool `json:"force_no_cache" mapstructure:"force_no_cache"`
|
||||
AuditNonHMACRequestKeys []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
|
||||
AuditNonHMACResponseKeys []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
|
||||
ListingVisibility string `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
|
||||
PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
|
||||
AllowedResponseHeaders []string `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
|
||||
TokenType string `json:"token_type,omitempty" mapstructure:"token_type"`
|
||||
|
||||
// Deprecated: This field will always be blank for newer server responses.
|
||||
PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
|
||||
}
|
339
vendor/github.com/hashicorp/vault/api/sys_plugins.go
generated
vendored
Normal file
339
vendor/github.com/hashicorp/vault/api/sys_plugins.go
generated
vendored
Normal file
@ -0,0 +1,339 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// ListPluginsInput is used as input to the ListPlugins function.
|
||||
type ListPluginsInput struct {
|
||||
// Type of the plugin. Required.
|
||||
Type consts.PluginType `json:"type"`
|
||||
}
|
||||
|
||||
// ListPluginsResponse is the response from the ListPlugins call.
|
||||
type ListPluginsResponse struct {
|
||||
// PluginsByType is the list of plugins by type.
|
||||
PluginsByType map[consts.PluginType][]string `json:"types"`
|
||||
|
||||
// Names is the list of names of the plugins.
|
||||
//
|
||||
// Deprecated: Newer server responses should be returning PluginsByType (json:
|
||||
// "types") instead.
|
||||
Names []string `json:"names"`
|
||||
}
|
||||
|
||||
// ListPlugins lists all plugins in the catalog and returns their names as a
|
||||
// list of strings.
|
||||
func (c *Sys) ListPlugins(i *ListPluginsInput) (*ListPluginsResponse, error) {
|
||||
path := ""
|
||||
method := ""
|
||||
if i.Type == consts.PluginTypeUnknown {
|
||||
path = "/v1/sys/plugins/catalog"
|
||||
method = "GET"
|
||||
} else {
|
||||
path = fmt.Sprintf("/v1/sys/plugins/catalog/%s", i.Type)
|
||||
method = "LIST"
|
||||
}
|
||||
|
||||
req := c.c.NewRequest(method, path)
|
||||
if method == "LIST" {
|
||||
// Set this for broader compatibility, but we use LIST above to be able
|
||||
// to handle the wrapping lookup function
|
||||
req.Method = "GET"
|
||||
req.Params.Set("list", "true")
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err != nil && resp == nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// We received an Unsupported Operation response from Vault, indicating
|
||||
// Vault of an older version that doesn't support the GET method yet;
|
||||
// switch it to a LIST.
|
||||
if resp.StatusCode == 405 {
|
||||
req.Params.Set("list", "true")
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
var result struct {
|
||||
Data struct {
|
||||
Keys []string `json:"keys"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := resp.DecodeJSON(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ListPluginsResponse{Names: result.Data.Keys}, nil
|
||||
}
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
result := &ListPluginsResponse{
|
||||
PluginsByType: make(map[consts.PluginType][]string),
|
||||
}
|
||||
if i.Type == consts.PluginTypeUnknown {
|
||||
for pluginTypeStr, pluginsRaw := range secret.Data {
|
||||
pluginType, err := consts.ParsePluginType(pluginTypeStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pluginsIfc, ok := pluginsRaw.([]interface{})
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to parse plugins for %q type", pluginTypeStr)
|
||||
}
|
||||
|
||||
plugins := make([]string, len(pluginsIfc))
|
||||
for i, nameIfc := range pluginsIfc {
|
||||
name, ok := nameIfc.(string)
|
||||
if !ok {
|
||||
|
||||
}
|
||||
plugins[i] = name
|
||||
}
|
||||
result.PluginsByType[pluginType] = plugins
|
||||
}
|
||||
} else {
|
||||
var respKeys []string
|
||||
if err := mapstructure.Decode(secret.Data["keys"], &respKeys); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.PluginsByType[i.Type] = respKeys
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetPluginInput is used as input to the GetPlugin function.
|
||||
type GetPluginInput struct {
|
||||
Name string `json:"-"`
|
||||
|
||||
// Type of the plugin. Required.
|
||||
Type consts.PluginType `json:"type"`
|
||||
}
|
||||
|
||||
// GetPluginResponse is the response from the GetPlugin call.
|
||||
type GetPluginResponse struct {
|
||||
Args []string `json:"args"`
|
||||
Builtin bool `json:"builtin"`
|
||||
Command string `json:"command"`
|
||||
Name string `json:"name"`
|
||||
SHA256 string `json:"sha256"`
|
||||
}
|
||||
|
||||
// GetPlugin retrieves information about the plugin.
|
||||
func (c *Sys) GetPlugin(i *GetPluginInput) (*GetPluginResponse, error) {
|
||||
path := catalogPathByType(i.Type, i.Name)
|
||||
req := c.c.NewRequest(http.MethodGet, path)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result struct {
|
||||
Data *GetPluginResponse
|
||||
}
|
||||
err = resp.DecodeJSON(&result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Data, err
|
||||
}
|
||||
|
||||
// RegisterPluginInput is used as input to the RegisterPlugin function.
|
||||
type RegisterPluginInput struct {
|
||||
// Name is the name of the plugin. Required.
|
||||
Name string `json:"-"`
|
||||
|
||||
// Type of the plugin. Required.
|
||||
Type consts.PluginType `json:"type"`
|
||||
|
||||
// Args is the list of args to spawn the process with.
|
||||
Args []string `json:"args,omitempty"`
|
||||
|
||||
// Command is the command to run.
|
||||
Command string `json:"command,omitempty"`
|
||||
|
||||
// SHA256 is the shasum of the plugin.
|
||||
SHA256 string `json:"sha256,omitempty"`
|
||||
}
|
||||
|
||||
// RegisterPlugin registers the plugin with the given information.
|
||||
func (c *Sys) RegisterPlugin(i *RegisterPluginInput) error {
|
||||
path := catalogPathByType(i.Type, i.Name)
|
||||
req := c.c.NewRequest(http.MethodPut, path)
|
||||
|
||||
if err := req.SetJSONBody(i); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// DeregisterPluginInput is used as input to the DeregisterPlugin function.
|
||||
type DeregisterPluginInput struct {
|
||||
// Name is the name of the plugin. Required.
|
||||
Name string `json:"-"`
|
||||
|
||||
// Type of the plugin. Required.
|
||||
Type consts.PluginType `json:"type"`
|
||||
}
|
||||
|
||||
// DeregisterPlugin removes the plugin with the given name from the plugin
|
||||
// catalog.
|
||||
func (c *Sys) DeregisterPlugin(i *DeregisterPluginInput) error {
|
||||
path := catalogPathByType(i.Type, i.Name)
|
||||
req := c.c.NewRequest(http.MethodDelete, path)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ReloadPluginInput is used as input to the ReloadPlugin function.
|
||||
type ReloadPluginInput struct {
|
||||
// Plugin is the name of the plugin to reload, as registered in the plugin catalog
|
||||
Plugin string `json:"plugin"`
|
||||
|
||||
// Mounts is the array of string mount paths of the plugin backends to reload
|
||||
Mounts []string `json:"mounts"`
|
||||
|
||||
// Scope is the scope of the plugin reload
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
// ReloadPlugin reloads mounted plugin backends, possibly returning
|
||||
// reloadId for a cluster scoped reload
|
||||
func (c *Sys) ReloadPlugin(i *ReloadPluginInput) (string, error) {
|
||||
path := "/v1/sys/plugins/reload/backend"
|
||||
req := c.c.NewRequest(http.MethodPut, path)
|
||||
|
||||
if err := req.SetJSONBody(i); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if i.Scope == "global" {
|
||||
// Get the reload id
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
if parseErr != nil {
|
||||
return "", parseErr
|
||||
}
|
||||
if _, ok := secret.Data["reload_id"]; ok {
|
||||
return secret.Data["reload_id"].(string), nil
|
||||
}
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
// ReloadStatus is the status of an individual node's plugin reload
|
||||
type ReloadStatus struct {
|
||||
Timestamp time.Time `json:"timestamp" mapstructure:"timestamp"`
|
||||
Error string `json:"error" mapstructure:"error"`
|
||||
}
|
||||
|
||||
// ReloadStatusResponse is the combined response of all known completed plugin reloads
|
||||
type ReloadStatusResponse struct {
|
||||
ReloadID string `mapstructure:"reload_id"`
|
||||
Results map[string]*ReloadStatus `mapstructure:"results"`
|
||||
}
|
||||
|
||||
// ReloadPluginStatusInput is used as input to the ReloadStatusPlugin function.
|
||||
type ReloadPluginStatusInput struct {
|
||||
// ReloadID is the ID of the reload operation
|
||||
ReloadID string `json:"reload_id"`
|
||||
}
|
||||
|
||||
// ReloadPluginStatus retrieves the status of a reload operation
|
||||
func (c *Sys) ReloadPluginStatus(reloadStatusInput *ReloadPluginStatusInput) (*ReloadStatusResponse, error) {
|
||||
path := "/v1/sys/plugins/reload/backend/status"
|
||||
req := c.c.NewRequest(http.MethodGet, path)
|
||||
req.Params.Add("reload_id", reloadStatusInput.ReloadID)
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
|
||||
resp, err := c.c.RawRequestWithContext(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp != nil {
|
||||
secret, parseErr := ParseSecret(resp.Body)
|
||||
if parseErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var r ReloadStatusResponse
|
||||
d, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||||
DecodeHook: mapstructure.StringToTimeHookFunc(time.RFC3339),
|
||||
Result: &r,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = d.Decode(secret.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &r, nil
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
|
||||
// catalogPathByType is a helper to construct the proper API path by plugin type
|
||||
func catalogPathByType(pluginType consts.PluginType, name string) string {
|
||||
path := fmt.Sprintf("/v1/sys/plugins/catalog/%s/%s", pluginType, name)
|
||||
|
||||
// Backwards compat, if type is not provided then use old path
|
||||
if pluginType == consts.PluginTypeUnknown {
|
||||
path = fmt.Sprintf("/v1/sys/plugins/catalog/%s", name)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
113
vendor/github.com/hashicorp/vault/api/sys_policy.go
generated
vendored
Normal file
113
vendor/github.com/hashicorp/vault/api/sys_policy.go
generated
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) ListPolicies() ([]string, error) {
|
||||
r := c.c.NewRequest("LIST", "/v1/sys/policies/acl")
|
||||
// Set this for broader compatibility, but we use LIST above to be able to
|
||||
// handle the wrapping lookup function
|
||||
r.Method = "GET"
|
||||
r.Params.Set("list", "true")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result []string
|
||||
err = mapstructure.Decode(secret.Data["keys"], &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (c *Sys) GetPolicy(name string) (string, error) {
|
||||
r := c.c.NewRequest("GET", fmt.Sprintf("/v1/sys/policies/acl/%s", name))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil {
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode == 404 {
|
||||
return "", nil
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return "", errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
if policyRaw, ok := secret.Data["policy"]; ok {
|
||||
return policyRaw.(string), nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no policy found in response")
|
||||
}
|
||||
|
||||
func (c *Sys) PutPolicy(name, rules string) error {
|
||||
body := map[string]string{
|
||||
"policy": rules,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/policies/acl/%s", name))
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Sys) DeletePolicy(name string) error {
|
||||
r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/policies/acl/%s", name))
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
type getPoliciesResp struct {
|
||||
Rules string `json:"rules"`
|
||||
}
|
||||
|
||||
type listPoliciesResp struct {
|
||||
Policies []string `json:"policies"`
|
||||
}
|
159
vendor/github.com/hashicorp/vault/api/sys_raft.go
generated
vendored
Normal file
159
vendor/github.com/hashicorp/vault/api/sys_raft.go
generated
vendored
Normal file
@ -0,0 +1,159 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
)
|
||||
|
||||
// RaftJoinResponse represents the response of the raft join API
|
||||
type RaftJoinResponse struct {
|
||||
Joined bool `json:"joined"`
|
||||
}
|
||||
|
||||
// RaftJoinRequest represents the parameters consumed by the raft join API
|
||||
type RaftJoinRequest struct {
|
||||
LeaderAPIAddr string `json:"leader_api_addr"`
|
||||
LeaderCACert string `json:"leader_ca_cert"`
|
||||
LeaderClientCert string `json:"leader_client_cert"`
|
||||
LeaderClientKey string `json:"leader_client_key"`
|
||||
Retry bool `json:"retry"`
|
||||
NonVoter bool `json:"non_voter"`
|
||||
}
|
||||
|
||||
// RaftJoin adds the node from which this call is invoked from to the raft
|
||||
// cluster represented by the leader address in the parameter.
|
||||
func (c *Sys) RaftJoin(opts *RaftJoinRequest) (*RaftJoinResponse, error) {
|
||||
r := c.c.NewRequest("POST", "/v1/sys/storage/raft/join")
|
||||
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RaftJoinResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
// RaftSnapshot invokes the API that takes the snapshot of the raft cluster and
|
||||
// writes it to the supplied io.Writer.
|
||||
func (c *Sys) RaftSnapshot(snapWriter io.Writer) error {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/storage/raft/snapshot")
|
||||
r.URL.RawQuery = r.Params.Encode()
|
||||
|
||||
req, err := http.NewRequest(http.MethodGet, r.URL.RequestURI(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req.URL.User = r.URL.User
|
||||
req.URL.Scheme = r.URL.Scheme
|
||||
req.URL.Host = r.URL.Host
|
||||
req.Host = r.URL.Host
|
||||
|
||||
if r.Headers != nil {
|
||||
for header, vals := range r.Headers {
|
||||
for _, val := range vals {
|
||||
req.Header.Add(header, val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ClientToken) != 0 {
|
||||
req.Header.Set(consts.AuthHeaderName, r.ClientToken)
|
||||
}
|
||||
|
||||
if len(r.WrapTTL) != 0 {
|
||||
req.Header.Set("X-Vault-Wrap-TTL", r.WrapTTL)
|
||||
}
|
||||
|
||||
if len(r.MFAHeaderVals) != 0 {
|
||||
for _, mfaHeaderVal := range r.MFAHeaderVals {
|
||||
req.Header.Add("X-Vault-MFA", mfaHeaderVal)
|
||||
}
|
||||
}
|
||||
|
||||
if r.PolicyOverride {
|
||||
req.Header.Set("X-Vault-Policy-Override", "true")
|
||||
}
|
||||
|
||||
// Avoiding the use of RawRequestWithContext which reads the response body
|
||||
// to determine if the body contains error message.
|
||||
var result *Response
|
||||
resp, err := c.c.config.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check for a redirect, only allowing for a single redirect
|
||||
if resp.StatusCode == 301 || resp.StatusCode == 302 || resp.StatusCode == 307 {
|
||||
// Parse the updated location
|
||||
respLoc, err := resp.Location()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Ensure a protocol downgrade doesn't happen
|
||||
if req.URL.Scheme == "https" && respLoc.Scheme != "https" {
|
||||
return fmt.Errorf("redirect would cause protocol downgrade")
|
||||
}
|
||||
|
||||
// Update the request
|
||||
req.URL = respLoc
|
||||
|
||||
// Retry the request
|
||||
resp, err = c.c.config.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
result = &Response{Response: resp}
|
||||
if err := result.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(snapWriter, resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RaftSnapshotRestore reads the snapshot from the io.Reader and installs that
|
||||
// snapshot, returning the cluster to the state defined by it.
|
||||
func (c *Sys) RaftSnapshotRestore(snapReader io.Reader, force bool) error {
|
||||
path := "/v1/sys/storage/raft/snapshot"
|
||||
if force {
|
||||
path = "/v1/sys/storage/raft/snapshot-force"
|
||||
}
|
||||
r := c.c.NewRequest("POST", path)
|
||||
|
||||
r.Body = snapReader
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
388
vendor/github.com/hashicorp/vault/api/sys_rekey.go
generated
vendored
Normal file
388
vendor/github.com/hashicorp/vault/api/sys_rekey.go
generated
vendored
Normal file
@ -0,0 +1,388 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func (c *Sys) RekeyStatus() (*RekeyStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/init")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyStatus() (*RekeyStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey-recovery-key/init")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyVerificationStatus() (*RekeyVerificationStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/verify")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyVerificationStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyVerificationStatus() (*RekeyVerificationStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey-recovery-key/verify")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyVerificationStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyInit(config *RekeyInitRequest) (*RekeyStatusResponse, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey/init")
|
||||
if err := r.SetJSONBody(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyInit(config *RekeyInitRequest) (*RekeyStatusResponse, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey-recovery-key/init")
|
||||
if err := r.SetJSONBody(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyCancel() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/init")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyCancel() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey-recovery-key/init")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyVerificationCancel() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/verify")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyVerificationCancel() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey-recovery-key/verify")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyUpdate(shard, nonce string) (*RekeyUpdateResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"key": shard,
|
||||
"nonce": nonce,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey/update")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyUpdateResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyUpdate(shard, nonce string) (*RekeyUpdateResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"key": shard,
|
||||
"nonce": nonce,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey-recovery-key/update")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyUpdateResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRetrieveBackup() (*RekeyRetrieveResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result RekeyRetrieveResponse
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRetrieveRecoveryBackup() (*RekeyRetrieveResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result RekeyRetrieveResponse
|
||||
err = mapstructure.Decode(secret.Data, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyDeleteBackup() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyDeleteRecoveryBackup() error {
|
||||
r := c.c.NewRequest("DELETE", "/v1/sys/rekey/recovery-key-backup")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyVerificationUpdate(shard, nonce string) (*RekeyVerificationUpdateResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"key": shard,
|
||||
"nonce": nonce,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey/verify")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyVerificationUpdateResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
func (c *Sys) RekeyRecoveryKeyVerificationUpdate(shard, nonce string) (*RekeyVerificationUpdateResponse, error) {
|
||||
body := map[string]interface{}{
|
||||
"key": shard,
|
||||
"nonce": nonce,
|
||||
}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/rekey-recovery-key/verify")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result RekeyVerificationUpdateResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type RekeyInitRequest struct {
|
||||
SecretShares int `json:"secret_shares"`
|
||||
SecretThreshold int `json:"secret_threshold"`
|
||||
StoredShares int `json:"stored_shares"`
|
||||
PGPKeys []string `json:"pgp_keys"`
|
||||
Backup bool
|
||||
RequireVerification bool `json:"require_verification"`
|
||||
}
|
||||
|
||||
type RekeyStatusResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Started bool `json:"started"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Required int `json:"required"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
VerificationRequired bool `json:"verification_required"`
|
||||
VerificationNonce string `json:"verification_nonce"`
|
||||
}
|
||||
|
||||
type RekeyUpdateResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
Keys []string `json:"keys"`
|
||||
KeysB64 []string `json:"keys_base64"`
|
||||
PGPFingerprints []string `json:"pgp_fingerprints"`
|
||||
Backup bool `json:"backup"`
|
||||
VerificationRequired bool `json:"verification_required"`
|
||||
VerificationNonce string `json:"verification_nonce,omitempty"`
|
||||
}
|
||||
|
||||
type RekeyRetrieveResponse struct {
|
||||
Nonce string `json:"nonce" mapstructure:"nonce"`
|
||||
Keys map[string][]string `json:"keys" mapstructure:"keys"`
|
||||
KeysB64 map[string][]string `json:"keys_base64" mapstructure:"keys_base64"`
|
||||
}
|
||||
|
||||
type RekeyVerificationStatusResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Started bool `json:"started"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
}
|
||||
|
||||
type RekeyVerificationUpdateResponse struct {
|
||||
Nonce string `json:"nonce"`
|
||||
Complete bool `json:"complete"`
|
||||
}
|
77
vendor/github.com/hashicorp/vault/api/sys_rotate.go
generated
vendored
Normal file
77
vendor/github.com/hashicorp/vault/api/sys_rotate.go
generated
vendored
Normal file
@ -0,0 +1,77 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Sys) Rotate() error {
|
||||
r := c.c.NewRequest("POST", "/v1/sys/rotate")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) KeyStatus() (*KeyStatus, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/key-status")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
secret, err := ParseSecret(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil || secret.Data == nil {
|
||||
return nil, errors.New("data from server response is empty")
|
||||
}
|
||||
|
||||
var result KeyStatus
|
||||
|
||||
termRaw, ok := secret.Data["term"]
|
||||
if !ok {
|
||||
return nil, errors.New("term not found in response")
|
||||
}
|
||||
term, ok := termRaw.(json.Number)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert term to a number")
|
||||
}
|
||||
term64, err := term.Int64()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.Term = int(term64)
|
||||
|
||||
installTimeRaw, ok := secret.Data["install_time"]
|
||||
if !ok {
|
||||
return nil, errors.New("install_time not found in response")
|
||||
}
|
||||
installTimeStr, ok := installTimeRaw.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert install_time to a string")
|
||||
}
|
||||
installTime, err := time.Parse(time.RFC3339Nano, installTimeStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result.InstallTime = installTime
|
||||
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type KeyStatus struct {
|
||||
Term int `json:"term"`
|
||||
InstallTime time.Time `json:"install_time"`
|
||||
}
|
87
vendor/github.com/hashicorp/vault/api/sys_seal.go
generated
vendored
Normal file
87
vendor/github.com/hashicorp/vault/api/sys_seal.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) SealStatus() (*SealStatusResponse, error) {
|
||||
r := c.c.NewRequest("GET", "/v1/sys/seal-status")
|
||||
return sealStatusRequest(c, r)
|
||||
}
|
||||
|
||||
func (c *Sys) Seal() error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/seal")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err == nil {
|
||||
defer resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Sys) ResetUnsealProcess() (*SealStatusResponse, error) {
|
||||
body := map[string]interface{}{"reset": true}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/unseal")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sealStatusRequest(c, r)
|
||||
}
|
||||
|
||||
func (c *Sys) Unseal(shard string) (*SealStatusResponse, error) {
|
||||
body := map[string]interface{}{"key": shard}
|
||||
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/unseal")
|
||||
if err := r.SetJSONBody(body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sealStatusRequest(c, r)
|
||||
}
|
||||
|
||||
func (c *Sys) UnsealWithOptions(opts *UnsealOpts) (*SealStatusResponse, error) {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/unseal")
|
||||
if err := r.SetJSONBody(opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return sealStatusRequest(c, r)
|
||||
}
|
||||
|
||||
func sealStatusRequest(c *Sys, r *Request) (*SealStatusResponse, error) {
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result SealStatusResponse
|
||||
err = resp.DecodeJSON(&result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
type SealStatusResponse struct {
|
||||
Type string `json:"type"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Sealed bool `json:"sealed"`
|
||||
T int `json:"t"`
|
||||
N int `json:"n"`
|
||||
Progress int `json:"progress"`
|
||||
Nonce string `json:"nonce"`
|
||||
Version string `json:"version"`
|
||||
Migration bool `json:"migration"`
|
||||
ClusterName string `json:"cluster_name,omitempty"`
|
||||
ClusterID string `json:"cluster_id,omitempty"`
|
||||
RecoverySeal bool `json:"recovery_seal"`
|
||||
StorageType string `json:"storage_type,omitempty"`
|
||||
}
|
||||
|
||||
type UnsealOpts struct {
|
||||
Key string `json:"key"`
|
||||
Reset bool `json:"reset"`
|
||||
Migrate bool `json:"migrate"`
|
||||
}
|
15
vendor/github.com/hashicorp/vault/api/sys_stepdown.go
generated
vendored
Normal file
15
vendor/github.com/hashicorp/vault/api/sys_stepdown.go
generated
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
package api
|
||||
|
||||
import "context"
|
||||
|
||||
func (c *Sys) StepDown() error {
|
||||
r := c.c.NewRequest("PUT", "/v1/sys/step-down")
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
defer cancelFunc()
|
||||
resp, err := c.c.RawRequestWithContext(ctx, r)
|
||||
if resp != nil && resp.Body != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return err
|
||||
}
|
256
vendor/github.com/hashicorp/vault/command/agent/auth/auth.go
generated
vendored
Normal file
256
vendor/github.com/hashicorp/vault/command/agent/auth/auth.go
generated
vendored
Normal file
@ -0,0 +1,256 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/sdk/helper/jsonutil"
|
||||
)
|
||||
|
||||
type AuthMethod interface {
|
||||
// Authenticate returns a mount path, header, request body, and error.
|
||||
// The header may be nil if no special header is needed.
|
||||
Authenticate(context.Context, *api.Client) (string, http.Header, map[string]interface{}, error)
|
||||
NewCreds() chan struct{}
|
||||
CredSuccess()
|
||||
Shutdown()
|
||||
}
|
||||
|
||||
type AuthConfig struct {
|
||||
Logger hclog.Logger
|
||||
MountPath string
|
||||
WrapTTL time.Duration
|
||||
Config map[string]interface{}
|
||||
}
|
||||
|
||||
// AuthHandler is responsible for keeping a token alive and renewed and passing
|
||||
// new tokens to the sink server
|
||||
type AuthHandler struct {
|
||||
DoneCh chan struct{}
|
||||
OutputCh chan string
|
||||
TemplateTokenCh chan string
|
||||
logger hclog.Logger
|
||||
client *api.Client
|
||||
random *rand.Rand
|
||||
wrapTTL time.Duration
|
||||
enableReauthOnNewCredentials bool
|
||||
enableTemplateTokenCh bool
|
||||
}
|
||||
|
||||
type AuthHandlerConfig struct {
|
||||
Logger hclog.Logger
|
||||
Client *api.Client
|
||||
WrapTTL time.Duration
|
||||
EnableReauthOnNewCredentials bool
|
||||
EnableTemplateTokenCh bool
|
||||
}
|
||||
|
||||
func NewAuthHandler(conf *AuthHandlerConfig) *AuthHandler {
|
||||
ah := &AuthHandler{
|
||||
DoneCh: make(chan struct{}),
|
||||
// This is buffered so that if we try to output after the sink server
|
||||
// has been shut down, during agent shutdown, we won't block
|
||||
OutputCh: make(chan string, 1),
|
||||
TemplateTokenCh: make(chan string, 1),
|
||||
logger: conf.Logger,
|
||||
client: conf.Client,
|
||||
random: rand.New(rand.NewSource(int64(time.Now().Nanosecond()))),
|
||||
wrapTTL: conf.WrapTTL,
|
||||
enableReauthOnNewCredentials: conf.EnableReauthOnNewCredentials,
|
||||
enableTemplateTokenCh: conf.EnableTemplateTokenCh,
|
||||
}
|
||||
|
||||
return ah
|
||||
}
|
||||
|
||||
func backoffOrQuit(ctx context.Context, backoff time.Duration) {
|
||||
select {
|
||||
case <-time.After(backoff):
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
|
||||
func (ah *AuthHandler) Run(ctx context.Context, am AuthMethod) {
|
||||
if am == nil {
|
||||
panic("nil auth method")
|
||||
}
|
||||
|
||||
ah.logger.Info("starting auth handler")
|
||||
defer func() {
|
||||
am.Shutdown()
|
||||
close(ah.OutputCh)
|
||||
close(ah.DoneCh)
|
||||
close(ah.TemplateTokenCh)
|
||||
ah.logger.Info("auth handler stopped")
|
||||
}()
|
||||
|
||||
credCh := am.NewCreds()
|
||||
if !ah.enableReauthOnNewCredentials {
|
||||
realCredCh := credCh
|
||||
credCh = nil
|
||||
if realCredCh != nil {
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case <-realCredCh:
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
if credCh == nil {
|
||||
credCh = make(chan struct{})
|
||||
}
|
||||
|
||||
var watcher *api.LifetimeWatcher
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
// Create a fresh backoff value
|
||||
backoff := 2*time.Second + time.Duration(ah.random.Int63()%int64(time.Second*2)-int64(time.Second))
|
||||
|
||||
ah.logger.Info("authenticating")
|
||||
path, header, data, err := am.Authenticate(ctx, ah.client)
|
||||
if err != nil {
|
||||
ah.logger.Error("error getting path or data from method", "error", err, "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
|
||||
clientToUse := ah.client
|
||||
if ah.wrapTTL > 0 {
|
||||
wrapClient, err := ah.client.Clone()
|
||||
if err != nil {
|
||||
ah.logger.Error("error creating client for wrapped call", "error", err, "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
wrapClient.SetWrappingLookupFunc(func(string, string) string {
|
||||
return ah.wrapTTL.String()
|
||||
})
|
||||
clientToUse = wrapClient
|
||||
}
|
||||
for key, values := range header {
|
||||
for _, value := range values {
|
||||
clientToUse.AddHeader(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
secret, err := clientToUse.Logical().Write(path, data)
|
||||
// Check errors/sanity
|
||||
if err != nil {
|
||||
ah.logger.Error("error authenticating", "error", err, "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
|
||||
switch {
|
||||
case ah.wrapTTL > 0:
|
||||
if secret.WrapInfo == nil {
|
||||
ah.logger.Error("authentication returned nil wrap info", "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
if secret.WrapInfo.Token == "" {
|
||||
ah.logger.Error("authentication returned empty wrapped client token", "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
wrappedResp, err := jsonutil.EncodeJSON(secret.WrapInfo)
|
||||
if err != nil {
|
||||
ah.logger.Error("failed to encode wrapinfo", "error", err, "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
ah.logger.Info("authentication successful, sending wrapped token to sinks and pausing")
|
||||
ah.OutputCh <- string(wrappedResp)
|
||||
if ah.enableTemplateTokenCh {
|
||||
ah.TemplateTokenCh <- string(wrappedResp)
|
||||
}
|
||||
|
||||
am.CredSuccess()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ah.logger.Info("shutdown triggered")
|
||||
continue
|
||||
|
||||
case <-credCh:
|
||||
ah.logger.Info("auth method found new credentials, re-authenticating")
|
||||
continue
|
||||
}
|
||||
|
||||
default:
|
||||
if secret == nil || secret.Auth == nil {
|
||||
ah.logger.Error("authentication returned nil auth info", "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
if secret.Auth.ClientToken == "" {
|
||||
ah.logger.Error("authentication returned empty client token", "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
ah.logger.Info("authentication successful, sending token to sinks")
|
||||
ah.OutputCh <- secret.Auth.ClientToken
|
||||
if ah.enableTemplateTokenCh {
|
||||
ah.TemplateTokenCh <- secret.Auth.ClientToken
|
||||
}
|
||||
|
||||
am.CredSuccess()
|
||||
}
|
||||
|
||||
if watcher != nil {
|
||||
watcher.Stop()
|
||||
}
|
||||
|
||||
watcher, err = ah.client.NewLifetimeWatcher(&api.LifetimeWatcherInput{
|
||||
Secret: secret,
|
||||
})
|
||||
if err != nil {
|
||||
ah.logger.Error("error creating lifetime watcher, backing off and retrying", "error", err, "backoff", backoff.Seconds())
|
||||
backoffOrQuit(ctx, backoff)
|
||||
continue
|
||||
}
|
||||
|
||||
// Start the renewal process
|
||||
ah.logger.Info("starting renewal process")
|
||||
go watcher.Renew()
|
||||
|
||||
LifetimeWatcherLoop:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
ah.logger.Info("shutdown triggered, stopping lifetime watcher")
|
||||
watcher.Stop()
|
||||
break LifetimeWatcherLoop
|
||||
|
||||
case err := <-watcher.DoneCh():
|
||||
ah.logger.Info("lifetime watcher done channel triggered")
|
||||
if err != nil {
|
||||
ah.logger.Error("error renewing token", "error", err)
|
||||
}
|
||||
break LifetimeWatcherLoop
|
||||
|
||||
case <-watcher.RenewCh():
|
||||
ah.logger.Info("renewed auth token")
|
||||
|
||||
case <-credCh:
|
||||
ah.logger.Info("auth method found new credentials, re-authenticating")
|
||||
break LifetimeWatcherLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
130
vendor/github.com/hashicorp/vault/command/agent/auth/kubernetes/kubernetes.go
generated
vendored
Normal file
130
vendor/github.com/hashicorp/vault/command/agent/auth/kubernetes/kubernetes.go
generated
vendored
Normal file
@ -0,0 +1,130 @@
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
hclog "github.com/hashicorp/go-hclog"
|
||||
"github.com/hashicorp/vault/api"
|
||||
"github.com/hashicorp/vault/command/agent/auth"
|
||||
)
|
||||
|
||||
const (
|
||||
serviceAccountFile = "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
||||
)
|
||||
|
||||
type kubernetesMethod struct {
|
||||
logger hclog.Logger
|
||||
mountPath string
|
||||
|
||||
role string
|
||||
|
||||
// tokenPath is an optional path to a projected service account token inside
|
||||
// the pod, for use instead of the default service account token.
|
||||
tokenPath string
|
||||
|
||||
// jwtData is a ReadCloser used to inject a ReadCloser for mocking tests.
|
||||
jwtData io.ReadCloser
|
||||
}
|
||||
|
||||
// NewKubernetesAuthMethod reads the user configuration and returns a configured
|
||||
// AuthMethod
|
||||
func NewKubernetesAuthMethod(conf *auth.AuthConfig) (auth.AuthMethod, error) {
|
||||
if conf == nil {
|
||||
return nil, errors.New("empty config")
|
||||
}
|
||||
if conf.Config == nil {
|
||||
return nil, errors.New("empty config data")
|
||||
}
|
||||
|
||||
k := &kubernetesMethod{
|
||||
logger: conf.Logger,
|
||||
mountPath: conf.MountPath,
|
||||
}
|
||||
|
||||
roleRaw, ok := conf.Config["role"]
|
||||
if !ok {
|
||||
return nil, errors.New("missing 'role' value")
|
||||
}
|
||||
k.role, ok = roleRaw.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert 'role' config value to string")
|
||||
}
|
||||
|
||||
tokenPathRaw, ok := conf.Config["token_path"]
|
||||
if ok {
|
||||
k.tokenPath, ok = tokenPathRaw.(string)
|
||||
if !ok {
|
||||
return nil, errors.New("could not convert 'token_path' config value to string")
|
||||
}
|
||||
}
|
||||
|
||||
if k.role == "" {
|
||||
return nil, errors.New("'role' value is empty")
|
||||
}
|
||||
|
||||
return k, nil
|
||||
}
|
||||
|
||||
func (k *kubernetesMethod) Authenticate(ctx context.Context, client *api.Client) (string, http.Header, map[string]interface{}, error) {
|
||||
k.logger.Trace("beginning authentication")
|
||||
|
||||
jwtString, err := k.readJWT()
|
||||
if err != nil {
|
||||
return "", nil, nil, errwrap.Wrapf("error reading JWT with Kubernetes Auth: {{err}}", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/login", k.mountPath), nil, map[string]interface{}{
|
||||
"role": k.role,
|
||||
"jwt": jwtString,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *kubernetesMethod) NewCreds() chan struct{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *kubernetesMethod) CredSuccess() {
|
||||
}
|
||||
|
||||
func (k *kubernetesMethod) Shutdown() {
|
||||
}
|
||||
|
||||
// readJWT reads the JWT data for the Agent to submit to Vault. The default is
|
||||
// to read the JWT from the default service account location, defined by the
|
||||
// constant serviceAccountFile. In normal use k.jwtData is nil at invocation and
|
||||
// the method falls back to reading the token path with os.Open, opening a file
|
||||
// from either the default location or from the token_path path specified in
|
||||
// configuration.
|
||||
func (k *kubernetesMethod) readJWT() (string, error) {
|
||||
// load configured token path if set, default to serviceAccountFile
|
||||
tokenFilePath := serviceAccountFile
|
||||
if k.tokenPath != "" {
|
||||
tokenFilePath = k.tokenPath
|
||||
}
|
||||
|
||||
data := k.jwtData
|
||||
// k.jwtData should only be non-nil in tests
|
||||
if data == nil {
|
||||
f, err := os.Open(tokenFilePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
data = f
|
||||
}
|
||||
defer data.Close()
|
||||
|
||||
contentBytes, err := ioutil.ReadAll(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return strings.TrimSpace(string(contentBytes)), nil
|
||||
}
|
363
vendor/github.com/hashicorp/vault/sdk/LICENSE
generated
vendored
Normal file
363
vendor/github.com/hashicorp/vault/sdk/LICENSE
generated
vendored
Normal file
@ -0,0 +1,363 @@
|
||||
Mozilla Public License, version 2.0
|
||||
|
||||
1. Definitions
|
||||
|
||||
1.1. "Contributor"
|
||||
|
||||
means each individual or legal entity that creates, contributes to the
|
||||
creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
|
||||
means the combination of the Contributions of others (if any) used by a
|
||||
Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
|
||||
means Source Code Form to which the initial Contributor has attached the
|
||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||
Modifications of such Source Code Form, in each case including portions
|
||||
thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
a. that the initial Contributor has attached the notice described in
|
||||
Exhibit B to the Covered Software; or
|
||||
|
||||
b. that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the terms of
|
||||
a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
|
||||
means a work that combines Covered Software with other material, in a
|
||||
separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
|
||||
means having the right to grant, to the maximum extent possible, whether
|
||||
at the time of the initial grant or subsequently, any and all of the
|
||||
rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
|
||||
means any of the following:
|
||||
|
||||
a. any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered Software; or
|
||||
|
||||
b. any new file in Source Code Form that contains any Covered Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the License,
|
||||
by the making, using, selling, offering for sale, having made, import,
|
||||
or transfer of either its Contributions or its Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
|
||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||
General Public License, Version 2.1, the GNU Affero General Public
|
||||
License, Version 3.0, or any later versions of those licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that controls, is
|
||||
controlled by, or is under common control with You. For purposes of this
|
||||
definition, "control" means (a) the power, direct or indirect, to cause
|
||||
the direction or management of such entity, whether by contract or
|
||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||
outstanding shares or beneficial ownership of such entity.
|
||||
|
||||
|
||||
2. License Grants and Conditions
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
a. under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||
sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
a. for any code that a Contributor has removed from Covered Software; or
|
||||
|
||||
b. for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
c. under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights to
|
||||
grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||
Section 2.1.
|
||||
|
||||
|
||||
3. Responsibilities
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
a. such Covered Software must also be made available in Source Code Form,
|
||||
as described in Section 3.1, and You must inform recipients of the
|
||||
Executable Form how they can obtain a copy of such Source Code Form by
|
||||
reasonable means in a timely manner, at a charge no more than the cost
|
||||
of distribution to the recipient; and
|
||||
|
||||
b. You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter the
|
||||
recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
||||
limitations of liability) contained within the Source Code Form of the
|
||||
Covered Software, except that You may alter any license notices to the
|
||||
extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this License
|
||||
with respect to some or all of the Covered Software due to statute,
|
||||
judicial order, or regulation then You must: (a) comply with the terms of
|
||||
this License to the maximum extent possible; and (b) describe the
|
||||
limitations and the code they affect. Such description must be placed in a
|
||||
text file included with all distributions of the Covered Software under
|
||||
this License. Except to the extent prohibited by statute or regulation,
|
||||
such description must be sufficiently detailed for a recipient of ordinary
|
||||
skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically if You
|
||||
fail to comply with any of its terms. However, if You become compliant,
|
||||
then the rights granted under this License from a particular Contributor
|
||||
are reinstated (a) provisionally, unless and until such Contributor
|
||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
||||
basis, if such Contributor fails to notify You of the non-compliance by
|
||||
some reasonable means prior to 60 days after You have come back into
|
||||
compliance. Moreover, Your grants from a particular Contributor are
|
||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
||||
non-compliance by some reasonable means, this is the first time You have
|
||||
received notice of non-compliance with this License from such
|
||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
||||
of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||
license agreements (excluding distributors and resellers) which have been
|
||||
validly granted by You or Your distributors under this License prior to
|
||||
termination shall survive termination.
|
||||
|
||||
6. Disclaimer of Warranty
|
||||
|
||||
Covered Software is provided under this License on an "as is" basis,
|
||||
without warranty of any kind, either expressed, implied, or statutory,
|
||||
including, without limitation, warranties that the Covered Software is free
|
||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
||||
The entire risk as to the quality and performance of the Covered Software
|
||||
is with You. Should any Covered Software prove defective in any respect,
|
||||
You (not any Contributor) assume the cost of any necessary servicing,
|
||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
||||
part of this License. No use of any Covered Software is authorized under
|
||||
this License except under this disclaimer.
|
||||
|
||||
7. Limitation of Liability
|
||||
|
||||
Under no circumstances and under no legal theory, whether tort (including
|
||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||
distributes Covered Software as permitted above, be liable to You for any
|
||||
direct, indirect, special, incidental, or consequential damages of any
|
||||
character including, without limitation, damages for lost profits, loss of
|
||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses, even if such party shall have been
|
||||
informed of the possibility of such damages. This limitation of liability
|
||||
shall not apply to liability for death or personal injury resulting from
|
||||
such party's negligence to the extent applicable law prohibits such
|
||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
||||
incidental or consequential damages, so this exclusion and limitation may
|
||||
not apply to You.
|
||||
|
||||
8. Litigation
|
||||
|
||||
Any litigation relating to this License may be brought only in the courts
|
||||
of a jurisdiction where the defendant maintains its principal place of
|
||||
business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
||||
in this Section shall prevent a party's ability to bring cross-claims or
|
||||
counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides that
|
||||
the language of a contract shall be construed against the drafter shall not
|
||||
be used to construe this License against a Contributor.
|
||||
|
||||
|
||||
10. Versions of the License
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses If You choose to distribute Source Code Form that is
|
||||
Incompatible With Secondary Licenses under the terms of this version of
|
||||
the License, the notice described in Exhibit B of this License must be
|
||||
attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
|
||||
This Source Code Form is subject to the
|
||||
terms of the Mozilla Public License, v.
|
||||
2.0. If a copy of the MPL was not
|
||||
distributed with this file, You can
|
||||
obtain one at
|
||||
http://mozilla.org/MPL/2.0/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular file,
|
||||
then You may include the notice in a location (such as a LICENSE file in a
|
||||
relevant directory) where a recipient would be likely to look for such a
|
||||
notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
|
||||
This Source Code Form is "Incompatible
|
||||
With Secondary Licenses", as defined by
|
||||
the Mozilla Public License, v. 2.0.
|
||||
|
207
vendor/github.com/hashicorp/vault/sdk/helper/compressutil/compress.go
generated
vendored
Normal file
207
vendor/github.com/hashicorp/vault/sdk/helper/compressutil/compress.go
generated
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
package compressutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/lzw"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/pierrec/lz4"
|
||||
)
|
||||
|
||||
const (
|
||||
// A byte value used as a canary prefix for the compressed information
|
||||
// which is used to distinguish if a JSON input is compressed or not.
|
||||
// The value of this constant should not be a first character of any
|
||||
// valid JSON string.
|
||||
|
||||
CompressionTypeGzip = "gzip"
|
||||
CompressionCanaryGzip byte = 'G'
|
||||
|
||||
CompressionTypeLZW = "lzw"
|
||||
CompressionCanaryLZW byte = 'L'
|
||||
|
||||
CompressionTypeSnappy = "snappy"
|
||||
CompressionCanarySnappy byte = 'S'
|
||||
|
||||
CompressionTypeLZ4 = "lz4"
|
||||
CompressionCanaryLZ4 byte = '4'
|
||||
)
|
||||
|
||||
// SnappyReadCloser embeds the snappy reader which implements the io.Reader
|
||||
// interface. The decompress procedure in this utility expects an
|
||||
// io.ReadCloser. This type implements the io.Closer interface to retain the
|
||||
// generic way of decompression.
|
||||
type CompressUtilReadCloser struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
// Close is a noop method implemented only to satisfy the io.Closer interface
|
||||
func (c *CompressUtilReadCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompressionConfig is used to select a compression type to be performed by
|
||||
// Compress and Decompress utilities.
|
||||
// Supported types are:
|
||||
// * CompressionTypeLZW
|
||||
// * CompressionTypeGzip
|
||||
// * CompressionTypeSnappy
|
||||
// * CompressionTypeLZ4
|
||||
//
|
||||
// When using CompressionTypeGzip, the compression levels can also be chosen:
|
||||
// * gzip.DefaultCompression
|
||||
// * gzip.BestSpeed
|
||||
// * gzip.BestCompression
|
||||
type CompressionConfig struct {
|
||||
// Type of the compression algorithm to be used
|
||||
Type string
|
||||
|
||||
// When using Gzip format, the compression level to employ
|
||||
GzipCompressionLevel int
|
||||
}
|
||||
|
||||
// Compress places the canary byte in a buffer and uses the same buffer to fill
|
||||
// in the compressed information of the given input. The configuration supports
|
||||
// two type of compression: LZW and Gzip. When using Gzip compression format,
|
||||
// if GzipCompressionLevel is not specified, the 'gzip.DefaultCompression' will
|
||||
// be assumed.
|
||||
func Compress(data []byte, config *CompressionConfig) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
var writer io.WriteCloser
|
||||
var err error
|
||||
|
||||
if config == nil {
|
||||
return nil, fmt.Errorf("config is nil")
|
||||
}
|
||||
|
||||
// Write the canary into the buffer and create writer to compress the
|
||||
// input data based on the configured type
|
||||
switch config.Type {
|
||||
case CompressionTypeLZW:
|
||||
buf.Write([]byte{CompressionCanaryLZW})
|
||||
writer = lzw.NewWriter(&buf, lzw.LSB, 8)
|
||||
|
||||
case CompressionTypeGzip:
|
||||
buf.Write([]byte{CompressionCanaryGzip})
|
||||
|
||||
switch {
|
||||
case config.GzipCompressionLevel == gzip.BestCompression,
|
||||
config.GzipCompressionLevel == gzip.BestSpeed,
|
||||
config.GzipCompressionLevel == gzip.DefaultCompression:
|
||||
// These are valid compression levels
|
||||
default:
|
||||
// If compression level is set to NoCompression or to
|
||||
// any invalid value, fallback to Defaultcompression
|
||||
config.GzipCompressionLevel = gzip.DefaultCompression
|
||||
}
|
||||
writer, err = gzip.NewWriterLevel(&buf, config.GzipCompressionLevel)
|
||||
|
||||
case CompressionTypeSnappy:
|
||||
buf.Write([]byte{CompressionCanarySnappy})
|
||||
writer = snappy.NewBufferedWriter(&buf)
|
||||
|
||||
case CompressionTypeLZ4:
|
||||
buf.Write([]byte{CompressionCanaryLZ4})
|
||||
writer = lz4.NewWriter(&buf)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported compression type")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("failed to create a compression writer: {{err}}", err)
|
||||
}
|
||||
|
||||
if writer == nil {
|
||||
return nil, fmt.Errorf("failed to create a compression writer")
|
||||
}
|
||||
|
||||
// Compress the input and place it in the same buffer containing the
|
||||
// canary byte.
|
||||
if _, err = writer.Write(data); err != nil {
|
||||
return nil, errwrap.Wrapf("failed to compress input data: err: {{err}}", err)
|
||||
}
|
||||
|
||||
// Close the io.WriteCloser
|
||||
if err = writer.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Return the compressed bytes with canary byte at the start
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// Decompress checks if the first byte in the input matches the canary byte.
|
||||
// If the first byte is a canary byte, then the input past the canary byte
|
||||
// will be decompressed using the method specified in the given configuration.
|
||||
// If the first byte isn't a canary byte, then the utility returns a boolean
|
||||
// value indicating that the input was not compressed.
|
||||
func Decompress(data []byte) ([]byte, bool, error) {
|
||||
var err error
|
||||
var reader io.ReadCloser
|
||||
if data == nil || len(data) == 0 {
|
||||
return nil, false, fmt.Errorf("'data' being decompressed is empty")
|
||||
}
|
||||
|
||||
canary := data[0]
|
||||
cData := data[1:]
|
||||
|
||||
switch canary {
|
||||
// If the first byte matches the canary byte, remove the canary
|
||||
// byte and try to decompress the data that is after the canary.
|
||||
case CompressionCanaryGzip:
|
||||
if len(data) < 2 {
|
||||
return nil, false, fmt.Errorf("invalid 'data' after the canary")
|
||||
}
|
||||
reader, err = gzip.NewReader(bytes.NewReader(cData))
|
||||
|
||||
case CompressionCanaryLZW:
|
||||
if len(data) < 2 {
|
||||
return nil, false, fmt.Errorf("invalid 'data' after the canary")
|
||||
}
|
||||
reader = lzw.NewReader(bytes.NewReader(cData), lzw.LSB, 8)
|
||||
|
||||
case CompressionCanarySnappy:
|
||||
if len(data) < 2 {
|
||||
return nil, false, fmt.Errorf("invalid 'data' after the canary")
|
||||
}
|
||||
reader = &CompressUtilReadCloser{
|
||||
Reader: snappy.NewReader(bytes.NewReader(cData)),
|
||||
}
|
||||
|
||||
case CompressionCanaryLZ4:
|
||||
if len(data) < 2 {
|
||||
return nil, false, fmt.Errorf("invalid 'data' after the canary")
|
||||
}
|
||||
reader = &CompressUtilReadCloser{
|
||||
Reader: lz4.NewReader(bytes.NewReader(cData)),
|
||||
}
|
||||
|
||||
default:
|
||||
// If the first byte doesn't match the canary byte, it means
|
||||
// that the content was not compressed at all. Indicate the
|
||||
// caller that the input was not compressed.
|
||||
return nil, true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, false, errwrap.Wrapf("failed to create a compression reader: {{err}}", err)
|
||||
}
|
||||
if reader == nil {
|
||||
return nil, false, fmt.Errorf("failed to create a compression reader")
|
||||
}
|
||||
|
||||
// Close the io.ReadCloser
|
||||
defer reader.Close()
|
||||
|
||||
// Read all the compressed data into a buffer
|
||||
var buf bytes.Buffer
|
||||
if _, err = io.Copy(&buf, reader); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), false, nil
|
||||
}
|
5
vendor/github.com/hashicorp/vault/sdk/helper/consts/agent.go
generated
vendored
Normal file
5
vendor/github.com/hashicorp/vault/sdk/helper/consts/agent.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
package consts
|
||||
|
||||
// AgentPathCacheClear is the path that the agent will use as its cache-clear
|
||||
// endpoint.
|
||||
const AgentPathCacheClear = "/agent/v1/cache-clear"
|
35
vendor/github.com/hashicorp/vault/sdk/helper/consts/consts.go
generated
vendored
Normal file
35
vendor/github.com/hashicorp/vault/sdk/helper/consts/consts.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package consts
|
||||
|
||||
const (
|
||||
// ExpirationRestoreWorkerCount specifies the number of workers to use while
|
||||
// restoring leases into the expiration manager
|
||||
ExpirationRestoreWorkerCount = 64
|
||||
|
||||
// NamespaceHeaderName is the header set to specify which namespace the
|
||||
// request is indented for.
|
||||
NamespaceHeaderName = "X-Vault-Namespace"
|
||||
|
||||
// AuthHeaderName is the name of the header containing the token.
|
||||
AuthHeaderName = "X-Vault-Token"
|
||||
|
||||
// RequestHeaderName is the name of the header used by the Agent for
|
||||
// SSRF protection.
|
||||
RequestHeaderName = "X-Vault-Request"
|
||||
|
||||
// PerformanceReplicationALPN is the negotiated protocol used for
|
||||
// performance replication.
|
||||
PerformanceReplicationALPN = "replication_v1"
|
||||
|
||||
// DRReplicationALPN is the negotiated protocol used for dr replication.
|
||||
DRReplicationALPN = "replication_dr_v1"
|
||||
|
||||
PerfStandbyALPN = "perf_standby_v1"
|
||||
|
||||
RequestForwardingALPN = "req_fw_sb-act_v1"
|
||||
|
||||
RaftStorageALPN = "raft_storage_v1"
|
||||
|
||||
// ReplicationResolverALPN is the negotiated protocol used for
|
||||
// resolving replicaiton addresses
|
||||
ReplicationResolverALPN = "replication_resolver_v1"
|
||||
)
|
21
vendor/github.com/hashicorp/vault/sdk/helper/consts/error.go
generated
vendored
Normal file
21
vendor/github.com/hashicorp/vault/sdk/helper/consts/error.go
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
package consts
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrSealed is returned if an operation is performed on a sealed barrier.
|
||||
// No operation is expected to succeed before unsealing
|
||||
ErrSealed = errors.New("Vault is sealed")
|
||||
|
||||
// ErrStandby is returned if an operation is performed on a standby Vault.
|
||||
// No operation is expected to succeed until active.
|
||||
ErrStandby = errors.New("Vault is in standby mode")
|
||||
|
||||
// ErrPathContainsParentReferences is returned when a path contains parent
|
||||
// references.
|
||||
ErrPathContainsParentReferences = errors.New("path cannot contain parent references")
|
||||
|
||||
// ErrInvalidWrappingToken is returned when checking for the validity of
|
||||
// a wrapping token that turns out to be invalid.
|
||||
ErrInvalidWrappingToken = errors.New("wrapping token is not valid or does not exist")
|
||||
)
|
59
vendor/github.com/hashicorp/vault/sdk/helper/consts/plugin_types.go
generated
vendored
Normal file
59
vendor/github.com/hashicorp/vault/sdk/helper/consts/plugin_types.go
generated
vendored
Normal file
@ -0,0 +1,59 @@
|
||||
package consts
|
||||
|
||||
import "fmt"
|
||||
|
||||
var PluginTypes = []PluginType{
|
||||
PluginTypeUnknown,
|
||||
PluginTypeCredential,
|
||||
PluginTypeDatabase,
|
||||
PluginTypeSecrets,
|
||||
}
|
||||
|
||||
type PluginType uint32
|
||||
|
||||
// This is a list of PluginTypes used by Vault.
|
||||
// If we need to add any in the future, it would
|
||||
// be best to add them to the _end_ of the list below
|
||||
// because they resolve to incrementing numbers,
|
||||
// which may be saved in state somewhere. Thus if
|
||||
// the name for one of those numbers changed because
|
||||
// a value were added to the middle, that could cause
|
||||
// the wrong plugin types to be read from storage
|
||||
// for a given underlying number. Example of the problem
|
||||
// here: https://play.golang.org/p/YAaPw5ww3er
|
||||
const (
|
||||
PluginTypeUnknown PluginType = iota
|
||||
PluginTypeCredential
|
||||
PluginTypeDatabase
|
||||
PluginTypeSecrets
|
||||
)
|
||||
|
||||
func (p PluginType) String() string {
|
||||
switch p {
|
||||
case PluginTypeUnknown:
|
||||
return "unknown"
|
||||
case PluginTypeCredential:
|
||||
return "auth"
|
||||
case PluginTypeDatabase:
|
||||
return "database"
|
||||
case PluginTypeSecrets:
|
||||
return "secret"
|
||||
default:
|
||||
return "unsupported"
|
||||
}
|
||||
}
|
||||
|
||||
func ParsePluginType(pluginType string) (PluginType, error) {
|
||||
switch pluginType {
|
||||
case "unknown":
|
||||
return PluginTypeUnknown, nil
|
||||
case "auth":
|
||||
return PluginTypeCredential, nil
|
||||
case "database":
|
||||
return PluginTypeDatabase, nil
|
||||
case "secret":
|
||||
return PluginTypeSecrets, nil
|
||||
default:
|
||||
return PluginTypeUnknown, fmt.Errorf("%q is not a supported plugin type", pluginType)
|
||||
}
|
||||
}
|
151
vendor/github.com/hashicorp/vault/sdk/helper/consts/replication.go
generated
vendored
Normal file
151
vendor/github.com/hashicorp/vault/sdk/helper/consts/replication.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
package consts
|
||||
|
||||
const (
|
||||
//N.B. This needs to be excluded from replication despite the name; it's
|
||||
//merely saying that this is cluster information for the replicated
|
||||
//cluster.
|
||||
CoreReplicatedClusterPrefix = "core/cluster/replicated/"
|
||||
CoreReplicatedClusterPrefixDR = "core/cluster/replicated-dr/"
|
||||
|
||||
CoreReplicatedClusterInfoPath = CoreReplicatedClusterPrefix + "info"
|
||||
CoreReplicatedClusterSecondariesPrefix = CoreReplicatedClusterPrefix + "secondaries/"
|
||||
CoreReplicatedClusterInfoPathDR = CoreReplicatedClusterPrefixDR + "info"
|
||||
CoreReplicatedClusterSecondariesPrefixDR = CoreReplicatedClusterPrefixDR + "secondaries/"
|
||||
|
||||
// This is an identifier for the current secondary in the replicated paths
|
||||
// manager. It should contain a character that is not allowed in secondary
|
||||
// ids to ensure it doesn't collide.
|
||||
CurrentReplicatedSecondaryIdentifier = ".current"
|
||||
CoreFeatureFlagPath = "core/cluster/feature-flags"
|
||||
)
|
||||
|
||||
type ReplicationState uint32
|
||||
|
||||
const (
|
||||
_ ReplicationState = iota
|
||||
OldReplicationPrimary
|
||||
OldReplicationSecondary
|
||||
OldReplicationBootstrapping
|
||||
// Don't add anything here. Adding anything to this Old block would cause
|
||||
// the rest of the values to change below. This was done originally to
|
||||
// ensure no overlap between old and new values.
|
||||
|
||||
ReplicationUnknown ReplicationState = 0
|
||||
ReplicationPerformancePrimary ReplicationState = 1 << iota // Note -- iota is 5 here!
|
||||
ReplicationPerformanceSecondary
|
||||
OldSplitReplicationBootstrapping
|
||||
ReplicationDRPrimary
|
||||
ReplicationDRSecondary
|
||||
ReplicationPerformanceBootstrapping
|
||||
ReplicationDRBootstrapping
|
||||
ReplicationPerformanceDisabled
|
||||
ReplicationDRDisabled
|
||||
ReplicationPerformanceStandby
|
||||
)
|
||||
|
||||
// We verify no change to the above values are made
|
||||
func init() {
|
||||
|
||||
if OldReplicationBootstrapping != 3 {
|
||||
panic("Replication Constants have changed")
|
||||
}
|
||||
|
||||
if ReplicationPerformancePrimary != 1<<5 {
|
||||
panic("Replication Constants have changed")
|
||||
}
|
||||
}
|
||||
|
||||
func (r ReplicationState) string() string {
|
||||
switch r {
|
||||
case ReplicationPerformanceSecondary:
|
||||
return "secondary"
|
||||
case ReplicationPerformancePrimary:
|
||||
return "primary"
|
||||
case ReplicationPerformanceBootstrapping:
|
||||
return "bootstrapping"
|
||||
case ReplicationPerformanceDisabled:
|
||||
return "disabled"
|
||||
case ReplicationDRPrimary:
|
||||
return "primary"
|
||||
case ReplicationDRSecondary:
|
||||
return "secondary"
|
||||
case ReplicationDRBootstrapping:
|
||||
return "bootstrapping"
|
||||
case ReplicationDRDisabled:
|
||||
return "disabled"
|
||||
}
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (r ReplicationState) StateStrings() []string {
|
||||
var ret []string
|
||||
if r.HasState(ReplicationPerformanceSecondary) {
|
||||
ret = append(ret, "perf-secondary")
|
||||
}
|
||||
if r.HasState(ReplicationPerformancePrimary) {
|
||||
ret = append(ret, "perf-primary")
|
||||
}
|
||||
if r.HasState(ReplicationPerformanceBootstrapping) {
|
||||
ret = append(ret, "perf-bootstrapping")
|
||||
}
|
||||
if r.HasState(ReplicationPerformanceDisabled) {
|
||||
ret = append(ret, "perf-disabled")
|
||||
}
|
||||
if r.HasState(ReplicationDRPrimary) {
|
||||
ret = append(ret, "dr-primary")
|
||||
}
|
||||
if r.HasState(ReplicationDRSecondary) {
|
||||
ret = append(ret, "dr-secondary")
|
||||
}
|
||||
if r.HasState(ReplicationDRBootstrapping) {
|
||||
ret = append(ret, "dr-bootstrapping")
|
||||
}
|
||||
if r.HasState(ReplicationDRDisabled) {
|
||||
ret = append(ret, "dr-disabled")
|
||||
}
|
||||
if r.HasState(ReplicationPerformanceStandby) {
|
||||
ret = append(ret, "perfstandby")
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r ReplicationState) GetDRString() string {
|
||||
switch {
|
||||
case r.HasState(ReplicationDRBootstrapping):
|
||||
return ReplicationDRBootstrapping.string()
|
||||
case r.HasState(ReplicationDRPrimary):
|
||||
return ReplicationDRPrimary.string()
|
||||
case r.HasState(ReplicationDRSecondary):
|
||||
return ReplicationDRSecondary.string()
|
||||
case r.HasState(ReplicationDRDisabled):
|
||||
return ReplicationDRDisabled.string()
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (r ReplicationState) GetPerformanceString() string {
|
||||
switch {
|
||||
case r.HasState(ReplicationPerformanceBootstrapping):
|
||||
return ReplicationPerformanceBootstrapping.string()
|
||||
case r.HasState(ReplicationPerformancePrimary):
|
||||
return ReplicationPerformancePrimary.string()
|
||||
case r.HasState(ReplicationPerformanceSecondary):
|
||||
return ReplicationPerformanceSecondary.string()
|
||||
case r.HasState(ReplicationPerformanceDisabled):
|
||||
return ReplicationPerformanceDisabled.string()
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (r ReplicationState) IsPrimaryState() bool {
|
||||
return r.HasState(ReplicationPerformancePrimary | ReplicationDRPrimary)
|
||||
}
|
||||
|
||||
func (r ReplicationState) HasState(flag ReplicationState) bool { return r&flag != 0 }
|
||||
func (r *ReplicationState) AddState(flag ReplicationState) { *r |= flag }
|
||||
func (r *ReplicationState) ClearState(flag ReplicationState) { *r &= ^flag }
|
||||
func (r *ReplicationState) ToggleState(flag ReplicationState) { *r ^= flag }
|
36
vendor/github.com/hashicorp/vault/sdk/helper/hclutil/hcl.go
generated
vendored
Normal file
36
vendor/github.com/hashicorp/vault/sdk/helper/hclutil/hcl.go
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
package hclutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/hcl/hcl/ast"
|
||||
)
|
||||
|
||||
// CheckHCLKeys checks whether the keys in the AST list contains any of the valid keys provided.
|
||||
func CheckHCLKeys(node ast.Node, valid []string) error {
|
||||
var list *ast.ObjectList
|
||||
switch n := node.(type) {
|
||||
case *ast.ObjectList:
|
||||
list = n
|
||||
case *ast.ObjectType:
|
||||
list = n.List
|
||||
default:
|
||||
return fmt.Errorf("cannot check HCL keys of type %T", n)
|
||||
}
|
||||
|
||||
validMap := make(map[string]struct{}, len(valid))
|
||||
for _, v := range valid {
|
||||
validMap[v] = struct{}{}
|
||||
}
|
||||
|
||||
var result error
|
||||
for _, item := range list.Items {
|
||||
key := item.Keys[0].Token.Value().(string)
|
||||
if _, ok := validMap[key]; !ok {
|
||||
result = multierror.Append(result, fmt.Errorf("invalid key %q on line %d", key, item.Assign.Line))
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
100
vendor/github.com/hashicorp/vault/sdk/helper/jsonutil/json.go
generated
vendored
Normal file
100
vendor/github.com/hashicorp/vault/sdk/helper/jsonutil/json.go
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
package jsonutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/vault/sdk/helper/compressutil"
|
||||
)
|
||||
|
||||
// Encodes/Marshals the given object into JSON
|
||||
func EncodeJSON(in interface{}) ([]byte, error) {
|
||||
if in == nil {
|
||||
return nil, fmt.Errorf("input for encoding is nil")
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
enc := json.NewEncoder(&buf)
|
||||
if err := enc.Encode(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// EncodeJSONAndCompress encodes the given input into JSON and compresses the
|
||||
// encoded value (using Gzip format BestCompression level, by default). A
|
||||
// canary byte is placed at the beginning of the returned bytes for the logic
|
||||
// in decompression method to identify compressed input.
|
||||
func EncodeJSONAndCompress(in interface{}, config *compressutil.CompressionConfig) ([]byte, error) {
|
||||
if in == nil {
|
||||
return nil, fmt.Errorf("input for encoding is nil")
|
||||
}
|
||||
|
||||
// First JSON encode the given input
|
||||
encodedBytes, err := EncodeJSON(in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
config = &compressutil.CompressionConfig{
|
||||
Type: compressutil.CompressionTypeGzip,
|
||||
GzipCompressionLevel: gzip.BestCompression,
|
||||
}
|
||||
}
|
||||
|
||||
return compressutil.Compress(encodedBytes, config)
|
||||
}
|
||||
|
||||
// DecodeJSON tries to decompress the given data. The call to decompress, fails
|
||||
// if the content was not compressed in the first place, which is identified by
|
||||
// a canary byte before the compressed data. If the data is not compressed, it
|
||||
// is JSON decoded directly. Otherwise the decompressed data will be JSON
|
||||
// decoded.
|
||||
func DecodeJSON(data []byte, out interface{}) error {
|
||||
if data == nil || len(data) == 0 {
|
||||
return fmt.Errorf("'data' being decoded is nil")
|
||||
}
|
||||
if out == nil {
|
||||
return fmt.Errorf("output parameter 'out' is nil")
|
||||
}
|
||||
|
||||
// Decompress the data if it was compressed in the first place
|
||||
decompressedBytes, uncompressed, err := compressutil.Decompress(data)
|
||||
if err != nil {
|
||||
return errwrap.Wrapf("failed to decompress JSON: {{err}}", err)
|
||||
}
|
||||
if !uncompressed && (decompressedBytes == nil || len(decompressedBytes) == 0) {
|
||||
return fmt.Errorf("decompressed data being decoded is invalid")
|
||||
}
|
||||
|
||||
// If the input supplied failed to contain the compression canary, it
|
||||
// will be notified by the compression utility. Decode the decompressed
|
||||
// input.
|
||||
if !uncompressed {
|
||||
data = decompressedBytes
|
||||
}
|
||||
|
||||
return DecodeJSONFromReader(bytes.NewReader(data), out)
|
||||
}
|
||||
|
||||
// Decodes/Unmarshals the given io.Reader pointing to a JSON, into a desired object
|
||||
func DecodeJSONFromReader(r io.Reader, out interface{}) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("'io.Reader' being decoded is nil")
|
||||
}
|
||||
if out == nil {
|
||||
return fmt.Errorf("output parameter 'out' is nil")
|
||||
}
|
||||
|
||||
dec := json.NewDecoder(r)
|
||||
|
||||
// While decoding JSON values, interpret the integer values as `json.Number`s instead of `float64`.
|
||||
dec.UseNumber()
|
||||
|
||||
// Since 'out' is an interface representing a pointer, pass it to the decoder without an '&'
|
||||
return dec.Decode(out)
|
||||
}
|
230
vendor/github.com/hashicorp/vault/sdk/helper/parseutil/parseutil.go
generated
vendored
Normal file
230
vendor/github.com/hashicorp/vault/sdk/helper/parseutil/parseutil.go
generated
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
package parseutil
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
sockaddr "github.com/hashicorp/go-sockaddr"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
func ParseDurationSecond(in interface{}) (time.Duration, error) {
|
||||
var dur time.Duration
|
||||
jsonIn, ok := in.(json.Number)
|
||||
if ok {
|
||||
in = jsonIn.String()
|
||||
}
|
||||
switch inp := in.(type) {
|
||||
case nil:
|
||||
// return default of zero
|
||||
case string:
|
||||
if inp == "" {
|
||||
return dur, nil
|
||||
}
|
||||
var err error
|
||||
// Look for a suffix otherwise its a plain second value
|
||||
if strings.HasSuffix(inp, "s") || strings.HasSuffix(inp, "m") || strings.HasSuffix(inp, "h") || strings.HasSuffix(inp, "ms") {
|
||||
dur, err = time.ParseDuration(inp)
|
||||
if err != nil {
|
||||
return dur, err
|
||||
}
|
||||
} else {
|
||||
// Plain integer
|
||||
secs, err := strconv.ParseInt(inp, 10, 64)
|
||||
if err != nil {
|
||||
return dur, err
|
||||
}
|
||||
dur = time.Duration(secs) * time.Second
|
||||
}
|
||||
case int:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case int32:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case int64:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case uint:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case uint32:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case uint64:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case float32:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case float64:
|
||||
dur = time.Duration(inp) * time.Second
|
||||
case time.Duration:
|
||||
dur = inp
|
||||
default:
|
||||
return 0, errors.New("could not parse duration from input")
|
||||
}
|
||||
|
||||
return dur, nil
|
||||
}
|
||||
|
||||
func ParseAbsoluteTime(in interface{}) (time.Time, error) {
|
||||
var t time.Time
|
||||
switch inp := in.(type) {
|
||||
case nil:
|
||||
// return default of zero
|
||||
return t, nil
|
||||
case string:
|
||||
// Allow RFC3339 with nanoseconds, or without,
|
||||
// or an epoch time as an integer.
|
||||
var err error
|
||||
t, err = time.Parse(time.RFC3339Nano, inp)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
t, err = time.Parse(time.RFC3339, inp)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
epochTime, err := strconv.ParseInt(inp, 10, 64)
|
||||
if err == nil {
|
||||
t = time.Unix(epochTime, 0)
|
||||
break
|
||||
}
|
||||
return t, errors.New("could not parse string as date and time")
|
||||
case json.Number:
|
||||
epochTime, err := inp.Int64()
|
||||
if err != nil {
|
||||
return t, err
|
||||
}
|
||||
t = time.Unix(epochTime, 0)
|
||||
case int:
|
||||
t = time.Unix(int64(inp), 0)
|
||||
case int32:
|
||||
t = time.Unix(int64(inp), 0)
|
||||
case int64:
|
||||
t = time.Unix(inp, 0)
|
||||
case uint:
|
||||
t = time.Unix(int64(inp), 0)
|
||||
case uint32:
|
||||
t = time.Unix(int64(inp), 0)
|
||||
case uint64:
|
||||
t = time.Unix(int64(inp), 0)
|
||||
default:
|
||||
return t, errors.New("could not parse time from input type")
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func ParseInt(in interface{}) (int64, error) {
|
||||
var ret int64
|
||||
jsonIn, ok := in.(json.Number)
|
||||
if ok {
|
||||
in = jsonIn.String()
|
||||
}
|
||||
switch in.(type) {
|
||||
case string:
|
||||
inp := in.(string)
|
||||
if inp == "" {
|
||||
return 0, nil
|
||||
}
|
||||
var err error
|
||||
left, err := strconv.ParseInt(inp, 10, 64)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret = left
|
||||
case int:
|
||||
ret = int64(in.(int))
|
||||
case int32:
|
||||
ret = int64(in.(int32))
|
||||
case int64:
|
||||
ret = in.(int64)
|
||||
case uint:
|
||||
ret = int64(in.(uint))
|
||||
case uint32:
|
||||
ret = int64(in.(uint32))
|
||||
case uint64:
|
||||
ret = int64(in.(uint64))
|
||||
default:
|
||||
return 0, errors.New("could not parse value from input")
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func ParseBool(in interface{}) (bool, error) {
|
||||
var result bool
|
||||
if err := mapstructure.WeakDecode(in, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func ParseString(in interface{}) (string, error) {
|
||||
var result string
|
||||
if err := mapstructure.WeakDecode(in, &result); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func ParseCommaStringSlice(in interface{}) ([]string, error) {
|
||||
rawString, ok := in.(string)
|
||||
if ok && rawString == "" {
|
||||
return []string{}, nil
|
||||
}
|
||||
var result []string
|
||||
config := &mapstructure.DecoderConfig{
|
||||
Result: &result,
|
||||
WeaklyTypedInput: true,
|
||||
DecodeHook: mapstructure.StringToSliceHookFunc(","),
|
||||
}
|
||||
decoder, err := mapstructure.NewDecoder(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := decoder.Decode(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return strutil.TrimStrings(result), nil
|
||||
}
|
||||
|
||||
func ParseAddrs(addrs interface{}) ([]*sockaddr.SockAddrMarshaler, error) {
|
||||
out := make([]*sockaddr.SockAddrMarshaler, 0)
|
||||
stringAddrs := make([]string, 0)
|
||||
|
||||
switch addrs.(type) {
|
||||
case string:
|
||||
stringAddrs = strutil.ParseArbitraryStringSlice(addrs.(string), ",")
|
||||
if len(stringAddrs) == 0 {
|
||||
return nil, fmt.Errorf("unable to parse addresses from %v", addrs)
|
||||
}
|
||||
|
||||
case []string:
|
||||
stringAddrs = addrs.([]string)
|
||||
|
||||
case []interface{}:
|
||||
for _, v := range addrs.([]interface{}) {
|
||||
stringAddr, ok := v.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("error parsing %v as string", v)
|
||||
}
|
||||
stringAddrs = append(stringAddrs, stringAddr)
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown address input type %T", addrs)
|
||||
}
|
||||
|
||||
for _, addr := range stringAddrs {
|
||||
sa, err := sockaddr.NewSockAddr(addr)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf(fmt.Sprintf("error parsing address %q: {{err}}", addr), err)
|
||||
}
|
||||
out = append(out, &sockaddr.SockAddrMarshaler{
|
||||
SockAddr: sa,
|
||||
})
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
447
vendor/github.com/hashicorp/vault/sdk/helper/strutil/strutil.go
generated
vendored
Normal file
447
vendor/github.com/hashicorp/vault/sdk/helper/strutil/strutil.go
generated
vendored
Normal file
@ -0,0 +1,447 @@
|
||||
package strutil
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
glob "github.com/ryanuber/go-glob"
|
||||
)
|
||||
|
||||
// StrListContainsGlob looks for a string in a list of strings and allows
|
||||
// globs.
|
||||
func StrListContainsGlob(haystack []string, needle string) bool {
|
||||
for _, item := range haystack {
|
||||
if glob.Glob(item, needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StrListContains looks for a string in a list of strings.
|
||||
func StrListContains(haystack []string, needle string) bool {
|
||||
for _, item := range haystack {
|
||||
if item == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// StrListSubset checks if a given list is a subset
|
||||
// of another set
|
||||
func StrListSubset(super, sub []string) bool {
|
||||
for _, item := range sub {
|
||||
if !StrListContains(super, item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ParseDedupAndSortStrings parses a comma separated list of strings
|
||||
// into a slice of strings. The return slice will be sorted and will
|
||||
// not contain duplicate or empty items.
|
||||
func ParseDedupAndSortStrings(input string, sep string) []string {
|
||||
input = strings.TrimSpace(input)
|
||||
parsed := []string{}
|
||||
if input == "" {
|
||||
// Don't return nil
|
||||
return parsed
|
||||
}
|
||||
return RemoveDuplicates(strings.Split(input, sep), false)
|
||||
}
|
||||
|
||||
// ParseDedupLowercaseAndSortStrings parses a comma separated list of
|
||||
// strings into a slice of strings. The return slice will be sorted and
|
||||
// will not contain duplicate or empty items. The values will be converted
|
||||
// to lower case.
|
||||
func ParseDedupLowercaseAndSortStrings(input string, sep string) []string {
|
||||
input = strings.TrimSpace(input)
|
||||
parsed := []string{}
|
||||
if input == "" {
|
||||
// Don't return nil
|
||||
return parsed
|
||||
}
|
||||
return RemoveDuplicates(strings.Split(input, sep), true)
|
||||
}
|
||||
|
||||
// ParseKeyValues parses a comma separated list of `<key>=<value>` tuples
|
||||
// into a map[string]string.
|
||||
func ParseKeyValues(input string, out map[string]string, sep string) error {
|
||||
if out == nil {
|
||||
return fmt.Errorf("'out is nil")
|
||||
}
|
||||
|
||||
keyValues := ParseDedupLowercaseAndSortStrings(input, sep)
|
||||
if len(keyValues) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, keyValue := range keyValues {
|
||||
shards := strings.Split(keyValue, "=")
|
||||
if len(shards) != 2 {
|
||||
return fmt.Errorf("invalid <key,value> format")
|
||||
}
|
||||
|
||||
key := strings.TrimSpace(shards[0])
|
||||
value := strings.TrimSpace(shards[1])
|
||||
if key == "" || value == "" {
|
||||
return fmt.Errorf("invalid <key,value> pair: key: %q value: %q", key, value)
|
||||
}
|
||||
out[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseArbitraryKeyValues parses arbitrary <key,value> tuples. The input
|
||||
// can be one of the following:
|
||||
// * JSON string
|
||||
// * Base64 encoded JSON string
|
||||
// * Comma separated list of `<key>=<value>` pairs
|
||||
// * Base64 encoded string containing comma separated list of
|
||||
// `<key>=<value>` pairs
|
||||
//
|
||||
// Input will be parsed into the output parameter, which should
|
||||
// be a non-nil map[string]string.
|
||||
func ParseArbitraryKeyValues(input string, out map[string]string, sep string) error {
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
return nil
|
||||
}
|
||||
if out == nil {
|
||||
return fmt.Errorf("'out' is nil")
|
||||
}
|
||||
|
||||
// Try to base64 decode the input. If successful, consider the decoded
|
||||
// value as input.
|
||||
inputBytes, err := base64.StdEncoding.DecodeString(input)
|
||||
if err == nil {
|
||||
input = string(inputBytes)
|
||||
}
|
||||
|
||||
// Try to JSON unmarshal the input. If successful, consider that the
|
||||
// metadata was supplied as JSON input.
|
||||
err = json.Unmarshal([]byte(input), &out)
|
||||
if err != nil {
|
||||
// If JSON unmarshalling fails, consider that the input was
|
||||
// supplied as a comma separated string of 'key=value' pairs.
|
||||
if err = ParseKeyValues(input, out, sep); err != nil {
|
||||
return errwrap.Wrapf("failed to parse the input: {{err}}", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the parsed input
|
||||
for key, value := range out {
|
||||
if key != "" && value == "" {
|
||||
return fmt.Errorf("invalid value for key %q", key)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseStringSlice parses a `sep`-separated list of strings into a
|
||||
// []string with surrounding whitespace removed.
|
||||
//
|
||||
// The output will always be a valid slice but may be of length zero.
|
||||
func ParseStringSlice(input string, sep string) []string {
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
splitStr := strings.Split(input, sep)
|
||||
ret := make([]string, len(splitStr))
|
||||
for i, val := range splitStr {
|
||||
ret[i] = strings.TrimSpace(val)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// ParseArbitraryStringSlice parses arbitrary string slice. The input
|
||||
// can be one of the following:
|
||||
// * JSON string
|
||||
// * Base64 encoded JSON string
|
||||
// * `sep` separated list of values
|
||||
// * Base64-encoded string containing a `sep` separated list of values
|
||||
//
|
||||
// Note that the separator is ignored if the input is found to already be in a
|
||||
// structured format (e.g., JSON)
|
||||
//
|
||||
// The output will always be a valid slice but may be of length zero.
|
||||
func ParseArbitraryStringSlice(input string, sep string) []string {
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// Try to base64 decode the input. If successful, consider the decoded
|
||||
// value as input.
|
||||
inputBytes, err := base64.StdEncoding.DecodeString(input)
|
||||
if err == nil {
|
||||
input = string(inputBytes)
|
||||
}
|
||||
|
||||
ret := []string{}
|
||||
|
||||
// Try to JSON unmarshal the input. If successful, consider that the
|
||||
// metadata was supplied as JSON input.
|
||||
err = json.Unmarshal([]byte(input), &ret)
|
||||
if err != nil {
|
||||
// If JSON unmarshalling fails, consider that the input was
|
||||
// supplied as a separated string of values.
|
||||
return ParseStringSlice(input, sep)
|
||||
}
|
||||
|
||||
if ret == nil {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// TrimStrings takes a slice of strings and returns a slice of strings
|
||||
// with trimmed spaces
|
||||
func TrimStrings(items []string) []string {
|
||||
ret := make([]string, len(items))
|
||||
for i, item := range items {
|
||||
ret[i] = strings.TrimSpace(item)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// RemoveDuplicates removes duplicate and empty elements from a slice of
|
||||
// strings. This also may convert the items in the slice to lower case and
|
||||
// returns a sorted slice.
|
||||
func RemoveDuplicates(items []string, lowercase bool) []string {
|
||||
itemsMap := map[string]bool{}
|
||||
for _, item := range items {
|
||||
item = strings.TrimSpace(item)
|
||||
if lowercase {
|
||||
item = strings.ToLower(item)
|
||||
}
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
itemsMap[item] = true
|
||||
}
|
||||
items = make([]string, 0, len(itemsMap))
|
||||
for item := range itemsMap {
|
||||
items = append(items, item)
|
||||
}
|
||||
sort.Strings(items)
|
||||
return items
|
||||
}
|
||||
|
||||
// RemoveDuplicatesStable removes duplicate and empty elements from a slice of
|
||||
// strings, preserving order (and case) of the original slice.
|
||||
// In all cases, strings are compared after trimming whitespace
|
||||
// If caseInsensitive, strings will be compared after ToLower()
|
||||
func RemoveDuplicatesStable(items []string, caseInsensitive bool) []string {
|
||||
itemsMap := make(map[string]bool, len(items))
|
||||
deduplicated := make([]string, 0, len(items))
|
||||
|
||||
for _, item := range items {
|
||||
key := strings.TrimSpace(item)
|
||||
if caseInsensitive {
|
||||
key = strings.ToLower(key)
|
||||
}
|
||||
if key == "" || itemsMap[key] {
|
||||
continue
|
||||
}
|
||||
itemsMap[key] = true
|
||||
deduplicated = append(deduplicated, item)
|
||||
}
|
||||
return deduplicated
|
||||
}
|
||||
|
||||
// RemoveEmpty removes empty elements from a slice of
|
||||
// strings
|
||||
func RemoveEmpty(items []string) []string {
|
||||
if len(items) == 0 {
|
||||
return items
|
||||
}
|
||||
itemsSlice := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
itemsSlice = append(itemsSlice, item)
|
||||
}
|
||||
return itemsSlice
|
||||
}
|
||||
|
||||
// EquivalentSlices checks whether the given string sets are equivalent, as in,
|
||||
// they contain the same values.
|
||||
func EquivalentSlices(a, b []string) bool {
|
||||
if a == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if a == nil || b == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// First we'll build maps to ensure unique values
|
||||
mapA := map[string]bool{}
|
||||
mapB := map[string]bool{}
|
||||
for _, keyA := range a {
|
||||
mapA[keyA] = true
|
||||
}
|
||||
for _, keyB := range b {
|
||||
mapB[keyB] = true
|
||||
}
|
||||
|
||||
// Now we'll build our checking slices
|
||||
var sortedA, sortedB []string
|
||||
for keyA := range mapA {
|
||||
sortedA = append(sortedA, keyA)
|
||||
}
|
||||
for keyB := range mapB {
|
||||
sortedB = append(sortedB, keyB)
|
||||
}
|
||||
sort.Strings(sortedA)
|
||||
sort.Strings(sortedB)
|
||||
|
||||
// Finally, compare
|
||||
if len(sortedA) != len(sortedB) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range sortedA {
|
||||
if sortedA[i] != sortedB[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// EqualStringMaps tests whether two map[string]string objects are equal.
|
||||
// Equal means both maps have the same sets of keys and values. This function
|
||||
// is 6-10x faster than a call to reflect.DeepEqual().
|
||||
func EqualStringMaps(a, b map[string]string) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
|
||||
for k := range a {
|
||||
v, ok := b[k]
|
||||
if !ok || a[k] != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// StrListDelete removes the first occurrence of the given item from the slice
|
||||
// of strings if the item exists.
|
||||
func StrListDelete(s []string, d string) []string {
|
||||
if s == nil {
|
||||
return s
|
||||
}
|
||||
|
||||
for index, element := range s {
|
||||
if element == d {
|
||||
return append(s[:index], s[index+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// GlobbedStringsMatch compares item to val with support for a leading and/or
|
||||
// trailing wildcard '*' in item.
|
||||
func GlobbedStringsMatch(item, val string) bool {
|
||||
if len(item) < 2 {
|
||||
return val == item
|
||||
}
|
||||
|
||||
hasPrefix := strings.HasPrefix(item, "*")
|
||||
hasSuffix := strings.HasSuffix(item, "*")
|
||||
|
||||
if hasPrefix && hasSuffix {
|
||||
return strings.Contains(val, item[1:len(item)-1])
|
||||
} else if hasPrefix {
|
||||
return strings.HasSuffix(val, item[1:])
|
||||
} else if hasSuffix {
|
||||
return strings.HasPrefix(val, item[:len(item)-1])
|
||||
}
|
||||
|
||||
return val == item
|
||||
}
|
||||
|
||||
// AppendIfMissing adds a string to a slice if the given string is not present
|
||||
func AppendIfMissing(slice []string, i string) []string {
|
||||
if StrListContains(slice, i) {
|
||||
return slice
|
||||
}
|
||||
return append(slice, i)
|
||||
}
|
||||
|
||||
// MergeSlices adds an arbitrary number of slices together, uniquely
|
||||
func MergeSlices(args ...[]string) []string {
|
||||
all := map[string]struct{}{}
|
||||
for _, slice := range args {
|
||||
for _, v := range slice {
|
||||
all[v] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]string, 0, len(all))
|
||||
for k := range all {
|
||||
result = append(result, k)
|
||||
}
|
||||
sort.Strings(result)
|
||||
return result
|
||||
}
|
||||
|
||||
// Difference returns the set difference (A - B) of the two given slices. The
|
||||
// result will also remove any duplicated values in set A regardless of whether
|
||||
// that matches any values in set B.
|
||||
func Difference(a, b []string, lowercase bool) []string {
|
||||
if len(a) == 0 {
|
||||
return a
|
||||
}
|
||||
if len(b) == 0 {
|
||||
if !lowercase {
|
||||
return a
|
||||
}
|
||||
newA := make([]string, len(a))
|
||||
for i, v := range a {
|
||||
newA[i] = strings.ToLower(v)
|
||||
}
|
||||
return newA
|
||||
}
|
||||
|
||||
a = RemoveDuplicates(a, lowercase)
|
||||
b = RemoveDuplicates(b, lowercase)
|
||||
|
||||
itemsMap := map[string]bool{}
|
||||
for _, aVal := range a {
|
||||
itemsMap[aVal] = true
|
||||
}
|
||||
|
||||
// Perform difference calculation
|
||||
for _, bVal := range b {
|
||||
if _, ok := itemsMap[bVal]; ok {
|
||||
itemsMap[bVal] = false
|
||||
}
|
||||
}
|
||||
|
||||
items := []string{}
|
||||
for item, exists := range itemsMap {
|
||||
if exists {
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
sort.Strings(items)
|
||||
return items
|
||||
}
|
Reference in New Issue
Block a user