remove unnecessary vendoring of cmd/cfssl

During dc9def6f93, which was a revert for
7a10073e4a we forgot to remove the extra
thing we started vendoring. So let's drop the cmd/cfssl

Change-Id: I308dc41cdb9b990f2b4ab8d59ad0445d5ac02e8c
k3s-v1.15.3
Davanum Srinivas 2019-04-11 16:50:41 -04:00
parent 9e83e6d1cd
commit 437a7333e3
No known key found for this signature in database
GPG Key ID: 80D83A796103BF59
265 changed files with 2 additions and 257197 deletions

570
Godeps/LICENSES generated
View File

@ -4328,35 +4328,6 @@ Exhibit B - “Incompatible With Secondary Licenses” Notice
================================================================================
================================================================================
= vendor/github.com/daaku/go.zipexe licensed under: =
The MIT License (MIT)
Copyright © 2012-2015 Carlos Castillo
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/daaku/go.zipexe/license 2285ef50c2d5083f5bb92af715e5a378
================================================================================
================================================================================
= vendor/github.com/davecgh/go-spew licensed under: =
@ -6073,35 +6044,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/github.com/GeertJohan/go.rice licensed under: =
Copyright (c) 2013, Geert-Johan Riemer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/github.com/GeertJohan/go.rice/LICENSE d5ffb28cde0ca932cbab7e1e1d52c20e
================================================================================
================================================================================
= vendor/github.com/ghodss/yaml licensed under: =
@ -8318,387 +8260,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SO
================================================================================
================================================================================
= vendor/github.com/go-sql-driver/mysql licensed under: =
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.
= vendor/github.com/go-sql-driver/mysql/LICENSE 815ca599c9df247a0c7f619bab123dad
================================================================================
================================================================================
= vendor/github.com/godbus/dbus licensed under: =
@ -12058,64 +11619,6 @@ limitations under the License.
================================================================================
================================================================================
= vendor/github.com/jmhodges/clock licensed under: =
The MIT License (MIT)
Copyright © 2014 Jeff Hodges <jeff@somethingsimilar.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
= vendor/github.com/jmhodges/clock/LICENSE bc91f6bbbc0460d728657b023f3f6596
================================================================================
================================================================================
= vendor/github.com/jmoiron/sqlx licensed under: =
Copyright (c) 2013, Jason Moiron
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
= vendor/github.com/jmoiron/sqlx/LICENSE 4353e10ea313ec47121dd2c7d89ce6b9
================================================================================
================================================================================
= vendor/github.com/jonboulle/clockwork licensed under: =
@ -12461,34 +11964,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/github.com/kisielk/sqlstruct licensed under: =
Copyright 2012 Kamil Kisiel <kamil@kamilkisiel.net>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
= vendor/github.com/kisielk/sqlstruct/LICENSE bc5911f8d3b8034f564b63d7ea436519
================================================================================
================================================================================
= vendor/github.com/konsorten/go-windows-terminal-sequences licensed under: =
@ -12541,22 +12016,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================
================================================================================
= vendor/github.com/lib/pq licensed under: =
Copyright (c) 2011-2013, 'pq' Contributors
Portions Copyright (C) 2011 Blake Mizerany
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
= vendor/github.com/lib/pq/LICENSE.md 0eab29964025b358179aa6d8f7db14bf
================================================================================
================================================================================
= vendor/github.com/libopenstorage/openstorage licensed under: =
@ -12954,35 +12413,6 @@ SOFTWARE.
================================================================================
================================================================================
= vendor/github.com/mattn/go-sqlite3 licensed under: =
The MIT License (MIT)
Copyright (c) 2014 Yasuhiro Matsumoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
= vendor/github.com/mattn/go-sqlite3/LICENSE 2b7590a6661bc1940f50329c495898c6
================================================================================
================================================================================
= vendor/github.com/matttproud/golang_protobuf_extensions licensed under: =

View File

@ -24,8 +24,6 @@ import (
_ "github.com/bazelbuild/buildtools/buildozer"
_ "github.com/cespare/prettybench"
_ "github.com/client9/misspell/cmd/misspell"
_ "github.com/cloudflare/cfssl/cmd/cfssl"
_ "github.com/cloudflare/cfssl/cmd/cfssljson"
_ "github.com/jstemmer/go-junit-report"
_ "github.com/jteeuwen/go-bindata/go-bindata"
_ "github.com/onsi/ginkgo/ginkgo"

8
go.mod
View File

@ -11,7 +11,6 @@ require (
cloud.google.com/go v0.0.0-20160913182117-3b1ae45394a2
github.com/Azure/azure-sdk-for-go v21.3.0+incompatible
github.com/Azure/go-autorest v11.1.0+incompatible
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da // indirect
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20181220005116-f8e995905100
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd
@ -47,7 +46,6 @@ require (
github.com/cyphar/filepath-securejoin v0.0.0-20170720062807-ae69057f2299 // indirect
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c
github.com/d2g/dhcp4client v0.0.0-20170829104524-6e570ed0a266
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb // indirect
github.com/davecgh/go-spew v1.1.1
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd
github.com/dnaeon/go-vcr v1.0.1 // indirect
@ -68,7 +66,6 @@ require (
github.com/go-openapi/strfmt v0.17.0
github.com/go-openapi/validate v0.18.0
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible // indirect
github.com/go-sql-driver/mysql v1.3.0 // indirect
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55
github.com/gogo/protobuf v1.1.1
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903
@ -90,19 +87,15 @@ require (
github.com/heketi/rest v0.0.0-20180404230133-aa6a65207413 // indirect
github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6 // indirect
github.com/heketi/utils v0.0.0-20170317161834-435bc5bdfa64 // indirect
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 // indirect
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade // indirect
github.com/jonboulle/clockwork v0.0.0-20141017032234-72f9bd7c4e0c
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024
github.com/jteeuwen/go-bindata v0.0.0-20151023091102-a0ff2567cfb7
github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22
github.com/karrick/godirwalk v1.7.5 // indirect
github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49 // indirect
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 // indirect
github.com/kr/pretty v0.0.0-20140812000539-f31442d60e51 // indirect
github.com/kr/text v0.0.0-20130911015532-6807e777504f // indirect
github.com/lib/pq v0.0.0-20180201184707-88edab080323 // indirect
github.com/libopenstorage/openstorage v0.0.0-20170906232338-093a0c388875
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
github.com/lithammer/dedent v1.1.0
@ -110,7 +103,6 @@ require (
github.com/magiconair/properties v0.0.0-20160816085511-61b492c03cf4 // indirect
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c // indirect
github.com/mattn/go-shellwords v0.0.0-20180605041737-f8471b0a71de // indirect
github.com/mattn/go-sqlite3 v1.6.0 // indirect
github.com/mesos/mesos-go v0.0.9 // indirect
github.com/mholt/caddy v0.0.0-20180213163048-2de495001514
github.com/miekg/dns v0.0.0-20160614162101-5d001d020961

16
go.sum
View File

@ -11,8 +11,6 @@ github.com/Azure/go-autorest v11.1.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY=
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da h1:UVU3a9pRUyLdnBtn60WjRl0s4SEyJc2ChCY56OAR6wI=
github.com/GeertJohan/go.rice v0.0.0-20170420135705-c02ca9a983da/go.mod h1:DgrzXonpdQbfN3uYaGz1EG4Sbhyum/MMIn6Cphlh2bw=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20181220005116-f8e995905100 h1:EXrpgbxknFeRM6X/OgRqcbVtl5zqUFD5eV8O8M1BLzo=
github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20181220005116-f8e995905100/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14=
github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab h1:UKkYhof1njT1/xq4SEg5z+VpTgjmNeHwPGRQl7takDI=
@ -97,8 +95,6 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c h1:Xo2rK1pzOm0jO6abTPIQw
github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ=
github.com/d2g/dhcp4client v0.0.0-20170829104524-6e570ed0a266 h1:1iKpuOrCnaRBKKNoChzmVDXeoFuCS7wsooRncvzVPxo=
github.com/d2g/dhcp4client v0.0.0-20170829104524-6e570ed0a266/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb h1:tUf55Po0vzOendQ7NWytcdK0VuzQmfAgvGBUOQvN0WA=
github.com/daaku/go.zipexe v0.0.0-20150329023125-a5fe2436ffcb/go.mod h1:U0vRfAucUOohvdCxt5MWLF+TePIL0xbCkbKIiV8TQCE=
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/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd h1:uVsMphB1eRx7xB1njzL3fuMdWRN8HtVzoUOItHMwv5c=
@ -161,8 +157,6 @@ github.com/go-openapi/validate v0.18.0 h1:PVXYcP1GkTl+XIAJnyJxOmK6CSG5Q1UcvoCvNO
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible h1:sUy/in/P6askYr16XJgTKq/0SZhiWsdg4WZGaLsGQkM=
github.com/go-ozzo/ozzo-validation v3.5.0+incompatible/go.mod h1:gsEKFIVnabGBt6mXmxK0MoFy+cZoTJY6mu5Ll3LVLBU=
github.com/go-sql-driver/mysql v1.3.0 h1:pgwjLi/dvffoP9aabwkT3AKpXQM93QARkjFhDDqC1UE=
github.com/go-sql-driver/mysql v1.3.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55 h1:oIgNYSrSUbNH5DJh6DMhU1PiOKOYIHNxrV3djLsLpEI=
github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw=
@ -233,10 +227,6 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548 h1:dYTbLf4m0a5u0KLmPfB6mgxbcV7588bOCx79hxa5Sr4=
github.com/jmhodges/clock v0.0.0-20160418191101-880ee4c33548/go.mod h1:hGT6jSUVzF6no3QaDSMLGLEHtHSBSefs+MgcDWnmhmo=
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade h1:ryslCsfLTV4Cm/9NXqCJirlbYodWqFiTH454IaSn/fY=
github.com/jmoiron/sqlx v0.0.0-20180124204410-05cef0741ade/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
github.com/jonboulle/clockwork v0.0.0-20141017032234-72f9bd7c4e0c h1:XpRROA6ssPlTwJI8/pH+61uieOkcJhmAFz25cu0B94Y=
github.com/jonboulle/clockwork v0.0.0-20141017032234-72f9bd7c4e0c/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE=
@ -252,8 +242,6 @@ github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22 h1:eLCQd4nxsC7sumk
github.com/kardianos/osext v0.0.0-20150410034420-8fef92e41e22/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/karrick/godirwalk v1.7.5 h1:VbzFqwXwNbAZoA6W5odrLr+hKK197CcENcPh6E/gJ0M=
github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34=
github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49 h1:o/c0aWEP/m6n61xlYW2QP4t9424qlJOsxugn5Zds2Rg=
github.com/kisielk/sqlstruct v0.0.0-20150923205031-648daed35d49/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q=
@ -263,8 +251,6 @@ github.com/kr/pretty v0.0.0-20140812000539-f31442d60e51 h1:kGEU5h0EzkNa+B8Q3e0Gl
github.com/kr/pretty v0.0.0-20140812000539-f31442d60e51/go.mod h1:Bvhd+E3laJ0AVkG0c9rmtZcnhV0HQ3+c3YxxqTvc/gA=
github.com/kr/text v0.0.0-20130911015532-6807e777504f h1:JaNmHIV9Eby6srQVWuiQ6n8ko2o/lG6udSRCbFZe1fs=
github.com/kr/text v0.0.0-20130911015532-6807e777504f/go.mod h1:sjUstKUATFIcff4qlB53Kml0wQPtJVc/3fWrmuUmcfA=
github.com/lib/pq v0.0.0-20180201184707-88edab080323 h1:Ou506ViB5uo2GloKFWIYi5hwRJn4AAOXuLVv8RMY9+4=
github.com/lib/pq v0.0.0-20180201184707-88edab080323/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/libopenstorage/openstorage v0.0.0-20170906232338-093a0c388875 h1:s+gZ8/rkYrWgN7xTMUISDw6nspgWyju2OCKmpFBrviQ=
github.com/libopenstorage/openstorage v0.0.0-20170906232338-093a0c388875/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
@ -281,8 +267,6 @@ github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c h1:N7uWGS2fTwH/4BwxbHi
github.com/marstr/guid v0.0.0-20170427235115-8bdf7d1a087c/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattn/go-shellwords v0.0.0-20180605041737-f8471b0a71de h1:ryDLMbZGgf2bSdLfdQFaJuuP4No40cDUt62Mdv+3TW8=
github.com/mattn/go-shellwords v0.0.0-20180605041737-f8471b0a71de/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-sqlite3 v1.6.0 h1:TDwTWbeII+88Qy55nWlof0DclgAtI4LqGujkYMzmQII=
github.com/mattn/go-sqlite3 v1.6.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mesos/mesos-go v0.0.9 h1:w8V5sOEnxzHZ2kAOy273v/HgbolyI6XI+qe5jx5u+Y0=

22
vendor/BUILD vendored
View File

@ -22,7 +22,6 @@ filegroup(
"//vendor/github.com/Azure/go-autorest/autorest:all-srcs",
"//vendor/github.com/Azure/go-autorest/logger:all-srcs",
"//vendor/github.com/Azure/go-autorest/version:all-srcs",
"//vendor/github.com/GeertJohan/go.rice:all-srcs",
"//vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud:all-srcs",
"//vendor/github.com/JeffAshton/win_pdh:all-srcs",
"//vendor/github.com/MakeNowJust/heredoc:all-srcs",
@ -74,29 +73,17 @@ filegroup(
"//vendor/github.com/cespare/prettybench:all-srcs",
"//vendor/github.com/chai2010/gettext-go/gettext:all-srcs",
"//vendor/github.com/client9/misspell:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api:all-srcs",
"//vendor/github.com/cloudflare/cfssl/auth:all-srcs",
"//vendor/github.com/cloudflare/cfssl/bundler:all-srcs",
"//vendor/github.com/cloudflare/cfssl/certdb:all-srcs",
"//vendor/github.com/cloudflare/cfssl/certinfo:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cmd/cfssl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cmd/cfssljson:all-srcs",
"//vendor/github.com/cloudflare/cfssl/config:all-srcs",
"//vendor/github.com/cloudflare/cfssl/crl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/crypto/pkcs7:all-srcs",
"//vendor/github.com/cloudflare/cfssl/csr:all-srcs",
"//vendor/github.com/cloudflare/cfssl/errors:all-srcs",
"//vendor/github.com/cloudflare/cfssl/helpers:all-srcs",
"//vendor/github.com/cloudflare/cfssl/info:all-srcs",
"//vendor/github.com/cloudflare/cfssl/initca:all-srcs",
"//vendor/github.com/cloudflare/cfssl/log:all-srcs",
"//vendor/github.com/cloudflare/cfssl/ocsp:all-srcs",
"//vendor/github.com/cloudflare/cfssl/revoke:all-srcs",
"//vendor/github.com/cloudflare/cfssl/scan:all-srcs",
"//vendor/github.com/cloudflare/cfssl/selfsign:all-srcs",
"//vendor/github.com/cloudflare/cfssl/ocsp/config:all-srcs",
"//vendor/github.com/cloudflare/cfssl/signer:all-srcs",
"//vendor/github.com/cloudflare/cfssl/ubiquity:all-srcs",
"//vendor/github.com/clusterhq/flocker-go:all-srcs",
"//vendor/github.com/codedellemc/goscaleio:all-srcs",
"//vendor/github.com/container-storage-interface/spec/lib/go/csi:all-srcs",
@ -167,7 +154,6 @@ filegroup(
"//vendor/github.com/cyphar/filepath-securejoin:all-srcs",
"//vendor/github.com/d2g/dhcp4:all-srcs",
"//vendor/github.com/d2g/dhcp4client:all-srcs",
"//vendor/github.com/daaku/go.zipexe:all-srcs",
"//vendor/github.com/davecgh/go-spew/spew:all-srcs",
"//vendor/github.com/daviddengcn/go-colortext:all-srcs",
"//vendor/github.com/dgrijalva/jwt-go:all-srcs",
@ -211,7 +197,6 @@ filegroup(
"//vendor/github.com/go-openapi/swag:all-srcs",
"//vendor/github.com/go-openapi/validate:all-srcs",
"//vendor/github.com/go-ozzo/ozzo-validation:all-srcs",
"//vendor/github.com/go-sql-driver/mysql:all-srcs",
"//vendor/github.com/godbus/dbus:all-srcs",
"//vendor/github.com/gogo/protobuf/gogoproto:all-srcs",
"//vendor/github.com/gogo/protobuf/plugin/compare:all-srcs",
@ -285,18 +270,14 @@ filegroup(
"//vendor/github.com/imdario/mergo:all-srcs",
"//vendor/github.com/inconshreveable/mousetrap:all-srcs",
"//vendor/github.com/jmespath/go-jmespath:all-srcs",
"//vendor/github.com/jmhodges/clock:all-srcs",
"//vendor/github.com/jmoiron/sqlx:all-srcs",
"//vendor/github.com/jonboulle/clockwork:all-srcs",
"//vendor/github.com/json-iterator/go:all-srcs",
"//vendor/github.com/jstemmer/go-junit-report:all-srcs",
"//vendor/github.com/jteeuwen/go-bindata:all-srcs",
"//vendor/github.com/kardianos/osext:all-srcs",
"//vendor/github.com/karrick/godirwalk:all-srcs",
"//vendor/github.com/kisielk/sqlstruct:all-srcs",
"//vendor/github.com/konsorten/go-windows-terminal-sequences:all-srcs",
"//vendor/github.com/kr/fs:all-srcs",
"//vendor/github.com/lib/pq:all-srcs",
"//vendor/github.com/libopenstorage/openstorage/api:all-srcs",
"//vendor/github.com/libopenstorage/openstorage/pkg/parser:all-srcs",
"//vendor/github.com/libopenstorage/openstorage/pkg/units:all-srcs",
@ -309,7 +290,6 @@ filegroup(
"//vendor/github.com/mailru/easyjson/jwriter:all-srcs",
"//vendor/github.com/marstr/guid:all-srcs",
"//vendor/github.com/mattn/go-shellwords:all-srcs",
"//vendor/github.com/mattn/go-sqlite3:all-srcs",
"//vendor/github.com/matttproud/golang_protobuf_extensions/pbutil:all-srcs",
"//vendor/github.com/mholt/caddy/caddyfile:all-srcs",
"//vendor/github.com/miekg/dns:all-srcs",

View File

@ -1,8 +0,0 @@
/example/example
/example/example.exe
/rice/rice
/rice/rice.exe
*.rice-box.go
*.rice-box.syso
.wercker

View File

@ -1,19 +0,0 @@
language: go
go:
- master
- 1.x.x
- 1.8.x
- 1.7.x
- 1.6.x
- 1.5.x
install:
- go get -t ./...
- env
- if [ "${TRAVIS_GO_VERSION%.*}" != "1.5" ]; then go get github.com/golang/lint/golint; fi
script:
- go build -x ./...
- go test -cover ./...
- go vet ./...
- if [ "${TRAVIS_GO_VERSION%.*}" != "1.5" ]; then golint .; fi

View File

@ -1,4 +0,0 @@
Geert-Johan Riemer <geertjohan@geertjohan.net>
Paul Maddox <paul.maddox@gmail.com>
Vincent Petithory <vincent.petithory@gmail.com>

View File

@ -1,42 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"appended.go",
"box.go",
"config.go",
"debug.go",
"embedded.go",
"file.go",
"http.go",
"sort.go",
"virtual.go",
"walk.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/GeertJohan/go.rice",
importpath = "github.com/GeertJohan/go.rice",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/GeertJohan/go.rice/embedded:go_default_library",
"//vendor/github.com/daaku/go.zipexe:go_default_library",
"//vendor/github.com/kardianos/osext:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/GeertJohan/go.rice/embedded:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,22 +0,0 @@
Copyright (c) 2013, Geert-Johan Riemer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,151 +0,0 @@
## go.rice
[![Build Status](https://travis-ci.org/GeertJohan/go.rice.png)](https://travis-ci.org/GeertJohan/go.rice)
[![Godoc](https://img.shields.io/badge/godoc-go.rice-blue.svg?style=flat-square)](https://godoc.org/github.com/GeertJohan/go.rice)
go.rice is a [Go](http://golang.org) package that makes working with resources such as html,js,css,images and templates very easy. During development `go.rice` will load required files directly from disk. Upon deployment it is easy to add all resource files to a executable using the `rice` tool, without changing the source code for your package. go.rice provides several methods to add resources to a binary.
### What does it do?
The first thing go.rice does is finding the correct absolute path for your resource files. Say you are executing go binary in your home directory, but your `html-files` are located in `$GOPATH/src/yourApplication/html-files`. `go.rice` will lookup the correct path for that directory (relative to the location of yourApplication). The only thing you have to do is include the resources using `rice.FindBox("html-files")`.
This only works when the source is available to the machine executing the binary. Which is always the case when the binary was installed with `go get` or `go install`. It might occur that you wish to simply provide a binary, without source. The `rice` tool analyses source code and finds call's to `rice.FindBox(..)` and adds the required directories to the executable binary. There are several methods to add these resources. You can 'embed' by generating go source code, or append the resource to the executable as zip file. In both cases `go.rice` will detect the embedded or appended resources and load those, instead of looking up files from disk.
### Installation
Use `go get` to install the package the `rice` tool.
```
go get github.com/GeertJohan/go.rice
go get github.com/GeertJohan/go.rice/rice
```
### Package usage
Import the package: `import "github.com/GeertJohan/go.rice"`
**Serving a static content folder over HTTP with a rice Box**
```go
http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
http.ListenAndServe(":8080", nil)
```
**Service a static content folder over HTTP at a non-root location**
```go
box := rice.MustFindBox("cssfiles")
cssFileServer := http.StripPrefix("/css/", http.FileServer(box.HTTPBox()))
http.Handle("/css/", cssFileServer)
http.ListenAndServe(":8080", nil)
```
Note the *trailing slash* in `/css/` in both the call to
`http.StripPrefix` and `http.Handle`.
**Loading a template**
```go
// find a rice.Box
templateBox, err := rice.FindBox("example-templates")
if err != nil {
log.Fatal(err)
}
// get file contents as string
templateString, err := templateBox.String("message.tmpl")
if err != nil {
log.Fatal(err)
}
// parse and execute the template
tmplMessage, err := template.New("message").Parse(templateString)
if err != nil {
log.Fatal(err)
}
tmplMessage.Execute(os.Stdout, map[string]string{"Message": "Hello, world!"})
```
Never call `FindBox()` or `MustFindBox()` from an `init()` function, as the boxes might have not been loaded at that time.
### Tool usage
The `rice` tool lets you add the resources to a binary executable so the files are not loaded from the filesystem anymore. This creates a 'standalone' executable. There are several ways to add the resources to a binary, each has pro's and con's but all will work without requiring changes to the way you load the resources.
#### embed-go
**Embed resources by generating Go source code**
This method must be executed before building. It generates a single Go source file called *rice-box.go* for each package, that is compiled by the go compiler into the binary.
The downside with this option is that the generated go source files can become very large, which will slow down compilation and require lots of memory to compile.
Execute the following commands:
```
rice embed-go
go build
```
*A Note on Symbolic Links*: `embed-go` uses the `os.Walk` function
from the standard library. The `os.Walk` function does **not** follow
symbolic links. So, when creating a box, be aware that any symbolic
links inside your box's directory will not be followed. **However**,
if the box itself is a symbolic link, its actual location will be
resolved first and then walked. In summary, if your box location is a
symbolic link, it will be followed but none of the symbolic links in
the box will be followed.
#### embed-syso
**Embed resources by generating a coff .syso file and some .go source code**
** This method is experimental and should not be used for production systems just yet **
This method must be executed before building. It generates a COFF .syso file and Go source file that are compiled by the go compiler into the binary.
Execute the following commands:
```
rice embed-syso
go build
```
#### append
**Append resources to executable as zip file**
This method changes an already built executable. It appends the resources as zip file to the binary. It makes compilation a lot faster and can be used with large resource files.
Downsides for appending are that it requires `zip` to be installed and does not provide a working Seek method.
Run the following commands to create a standalone executable.
```
go build -o example
rice append --exec example
```
**Note: requires zip command to be installed**
On windows, install zip from http://gnuwin32.sourceforge.net/packages/zip.htm or cygwin/msys toolsets.
#### Help information
Run `rice -h` for information about all options.
You can run the -h option for each sub-command, e.g. `rice append -h`.
### Order of precedence
When opening a new box, the rice package tries to locate the resources in the following order:
- embedded in generated go source
- appended as zip
- 'live' from filesystem
### License
This project is licensed under a Simplified BSD license. Please read the [LICENSE file][license].
### TODO & Development
This package is not completed yet. Though it already provides working embedding, some important featuers are still missing.
- implement Readdir() correctly on virtualDir
- in-code TODO's
- find boxes in imported packages
Less important stuff:
- idea, os/arch dependent embeds. rice checks if embedding file has _os_arch or build flags. If box is not requested by file without buildflags, then the buildflags are applied to the embed file.
### Package documentation
You will find package documentation at [godoc.org/github.com/GeertJohan/go.rice][godoc].
[license]: https://github.com/GeertJohan/go.rice/blob/master/LICENSE
[godoc]: http://godoc.org/github.com/GeertJohan/go.rice

View File

@ -1,138 +0,0 @@
package rice
import (
"archive/zip"
"log"
"os"
"path/filepath"
"strings"
"time"
"github.com/daaku/go.zipexe"
"github.com/kardianos/osext"
)
// appendedBox defines an appended box
type appendedBox struct {
Name string // box name
Files map[string]*appendedFile // appended files (*zip.File) by full path
}
type appendedFile struct {
zipFile *zip.File
dir bool
dirInfo *appendedDirInfo
children []*appendedFile
content []byte
}
// appendedBoxes is a public register of appendes boxes
var appendedBoxes = make(map[string]*appendedBox)
func init() {
// find if exec is appended
thisFile, err := osext.Executable()
if err != nil {
return // not appended or cant find self executable
}
closer, rd, err := zipexe.OpenCloser(thisFile)
if err != nil {
return // not appended
}
defer closer.Close()
for _, f := range rd.File {
// get box and file name from f.Name
fileParts := strings.SplitN(strings.TrimLeft(filepath.ToSlash(f.Name), "/"), "/", 2)
boxName := fileParts[0]
var fileName string
if len(fileParts) > 1 {
fileName = fileParts[1]
}
// find box or create new one if doesn't exist
box := appendedBoxes[boxName]
if box == nil {
box = &appendedBox{
Name: boxName,
Files: make(map[string]*appendedFile),
}
appendedBoxes[boxName] = box
}
// create and add file to box
af := &appendedFile{
zipFile: f,
}
if f.Comment == "dir" {
af.dir = true
af.dirInfo = &appendedDirInfo{
name: filepath.Base(af.zipFile.Name),
//++ TODO: use zip modtime when that is set correctly: af.zipFile.ModTime()
time: time.Now(),
}
} else {
// this is a file, we need it's contents so we can create a bytes.Reader when the file is opened
// make a new byteslice
af.content = make([]byte, af.zipFile.FileInfo().Size())
// ignore reading empty files from zip (empty file still is a valid file to be read though!)
if len(af.content) > 0 {
// open io.ReadCloser
rc, err := af.zipFile.Open()
if err != nil {
af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
// TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
log.Printf("error opening appended file %s: %v", af.zipFile.Name, err)
} else {
_, err = rc.Read(af.content)
rc.Close()
if err != nil {
af.content = nil // this will cause an error when the file is being opened or seeked (which is good)
// TODO: it's quite blunt to just log this stuff. but this is in init, so rice.Debug can't be changed yet..
log.Printf("error reading data for appended file %s: %v", af.zipFile.Name, err)
}
}
}
}
// add appendedFile to box file list
box.Files[fileName] = af
// add to parent dir (if any)
dirName := filepath.Dir(fileName)
if dirName == "." {
dirName = ""
}
if fileName != "" { // don't make box root dir a child of itself
if dir := box.Files[dirName]; dir != nil {
dir.children = append(dir.children, af)
}
}
}
}
// implements os.FileInfo.
// used for Readdir()
type appendedDirInfo struct {
name string
time time.Time
}
func (adi *appendedDirInfo) Name() string {
return adi.name
}
func (adi *appendedDirInfo) Size() int64 {
return 0
}
func (adi *appendedDirInfo) Mode() os.FileMode {
return os.ModeDir
}
func (adi *appendedDirInfo) ModTime() time.Time {
return adi.time
}
func (adi *appendedDirInfo) IsDir() bool {
return true
}
func (adi *appendedDirInfo) Sys() interface{} {
return nil
}

View File

@ -1,337 +0,0 @@
package rice
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/GeertJohan/go.rice/embedded"
)
// Box abstracts a directory for resources/files.
// It can either load files from disk, or from embedded code (when `rice --embed` was ran).
type Box struct {
name string
absolutePath string
embed *embedded.EmbeddedBox
appendd *appendedBox
}
var defaultLocateOrder = []LocateMethod{LocateEmbedded, LocateAppended, LocateFS}
func findBox(name string, order []LocateMethod) (*Box, error) {
b := &Box{name: name}
// no support for absolute paths since gopath can be different on different machines.
// therefore, required box must be located relative to package requiring it.
if filepath.IsAbs(name) {
return nil, errors.New("given name/path is absolute")
}
var err error
for _, method := range order {
switch method {
case LocateEmbedded:
if embed := embedded.EmbeddedBoxes[name]; embed != nil {
b.embed = embed
return b, nil
}
case LocateAppended:
appendedBoxName := strings.Replace(name, `/`, `-`, -1)
if appendd := appendedBoxes[appendedBoxName]; appendd != nil {
b.appendd = appendd
return b, nil
}
case LocateFS:
// resolve absolute directory path
err := b.resolveAbsolutePathFromCaller()
if err != nil {
continue
}
// check if absolutePath exists on filesystem
info, err := os.Stat(b.absolutePath)
if err != nil {
continue
}
// check if absolutePath is actually a directory
if !info.IsDir() {
err = errors.New("given name/path is not a directory")
continue
}
return b, nil
case LocateWorkingDirectory:
// resolve absolute directory path
err := b.resolveAbsolutePathFromWorkingDirectory()
if err != nil {
continue
}
// check if absolutePath exists on filesystem
info, err := os.Stat(b.absolutePath)
if err != nil {
continue
}
// check if absolutePath is actually a directory
if !info.IsDir() {
err = errors.New("given name/path is not a directory")
continue
}
return b, nil
}
}
if err == nil {
err = fmt.Errorf("could not locate box %q", name)
}
return nil, err
}
// FindBox returns a Box instance for given name.
// When the given name is a relative path, it's base path will be the calling pkg/cmd's source root.
// When the given name is absolute, it's absolute. derp.
// Make sure the path doesn't contain any sensitive information as it might be placed into generated go source (embedded).
func FindBox(name string) (*Box, error) {
return findBox(name, defaultLocateOrder)
}
// MustFindBox returns a Box instance for given name, like FindBox does.
// It does not return an error, instead it panics when an error occurs.
func MustFindBox(name string) *Box {
box, err := findBox(name, defaultLocateOrder)
if err != nil {
panic(err)
}
return box
}
// This is injected as a mutable function literal so that we can mock it out in
// tests and return a fixed test file.
var resolveAbsolutePathFromCaller = func(name string, nStackFrames int) (string, error) {
_, callingGoFile, _, ok := runtime.Caller(nStackFrames)
if !ok {
return "", errors.New("couldn't find caller on stack")
}
// resolve to proper path
pkgDir := filepath.Dir(callingGoFile)
// fix for go cover
const coverPath = "_test/_obj_test"
if !filepath.IsAbs(pkgDir) {
if i := strings.Index(pkgDir, coverPath); i >= 0 {
pkgDir = pkgDir[:i] + pkgDir[i+len(coverPath):] // remove coverPath
pkgDir = filepath.Join(os.Getenv("GOPATH"), "src", pkgDir) // make absolute
}
}
return filepath.Join(pkgDir, name), nil
}
func (b *Box) resolveAbsolutePathFromCaller() error {
path, err := resolveAbsolutePathFromCaller(b.name, 4)
if err != nil {
return err
}
b.absolutePath = path
return nil
}
func (b *Box) resolveAbsolutePathFromWorkingDirectory() error {
path, err := os.Getwd()
if err != nil {
return err
}
b.absolutePath = filepath.Join(path, b.name)
return nil
}
// IsEmbedded indicates wether this box was embedded into the application
func (b *Box) IsEmbedded() bool {
return b.embed != nil
}
// IsAppended indicates wether this box was appended to the application
func (b *Box) IsAppended() bool {
return b.appendd != nil
}
// Time returns how actual the box is.
// When the box is embedded, it's value is saved in the embedding code.
// When the box is live, this methods returns time.Now()
func (b *Box) Time() time.Time {
if b.IsEmbedded() {
return b.embed.Time
}
//++ TODO: return time for appended box
return time.Now()
}
// Open opens a File from the box
// If there is an error, it will be of type *os.PathError.
func (b *Box) Open(name string) (*File, error) {
if Debug {
fmt.Printf("Open(%s)\n", name)
}
if b.IsEmbedded() {
if Debug {
fmt.Println("Box is embedded")
}
// trim prefix (paths are relative to box)
name = strings.TrimLeft(name, "/")
if Debug {
fmt.Printf("Trying %s\n", name)
}
// search for file
ef := b.embed.Files[name]
if ef == nil {
if Debug {
fmt.Println("Didn't find file in embed")
}
// file not found, try dir
ed := b.embed.Dirs[name]
if ed == nil {
if Debug {
fmt.Println("Didn't find dir in embed")
}
// dir not found, error out
return nil, &os.PathError{
Op: "open",
Path: name,
Err: os.ErrNotExist,
}
}
if Debug {
fmt.Println("Found dir. Returning virtual dir")
}
vd := newVirtualDir(ed)
return &File{virtualD: vd}, nil
}
// box is embedded
if Debug {
fmt.Println("Found file. Returning virtual file")
}
vf := newVirtualFile(ef)
return &File{virtualF: vf}, nil
}
if b.IsAppended() {
// trim prefix (paths are relative to box)
name = strings.TrimLeft(name, "/")
// search for file
appendedFile := b.appendd.Files[name]
if appendedFile == nil {
return nil, &os.PathError{
Op: "open",
Path: name,
Err: os.ErrNotExist,
}
}
// create new file
f := &File{
appendedF: appendedFile,
}
// if this file is a directory, we want to be able to read and seek
if !appendedFile.dir {
// looks like malformed data in zip, error now
if appendedFile.content == nil {
return nil, &os.PathError{
Op: "open",
Path: "name",
Err: errors.New("error reading data from zip file"),
}
}
// create new bytes.Reader
f.appendedFileReader = bytes.NewReader(appendedFile.content)
}
// all done
return f, nil
}
// perform os open
if Debug {
fmt.Printf("Using os.Open(%s)", filepath.Join(b.absolutePath, name))
}
file, err := os.Open(filepath.Join(b.absolutePath, name))
if err != nil {
return nil, err
}
return &File{realF: file}, nil
}
// Bytes returns the content of the file with given name as []byte.
func (b *Box) Bytes(name string) ([]byte, error) {
file, err := b.Open(name)
if err != nil {
return nil, err
}
defer file.Close()
content, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
return content, nil
}
// MustBytes returns the content of the file with given name as []byte.
// panic's on error.
func (b *Box) MustBytes(name string) []byte {
bts, err := b.Bytes(name)
if err != nil {
panic(err)
}
return bts
}
// String returns the content of the file with given name as string.
func (b *Box) String(name string) (string, error) {
// check if box is embedded, optimized fast path
if b.IsEmbedded() {
// find file in embed
ef := b.embed.Files[name]
if ef == nil {
return "", os.ErrNotExist
}
// return as string
return ef.Content, nil
}
bts, err := b.Bytes(name)
if err != nil {
return "", err
}
return string(bts), nil
}
// MustString returns the content of the file with given name as string.
// panic's on error.
func (b *Box) MustString(name string) string {
str, err := b.String(name)
if err != nil {
panic(err)
}
return str
}
// Name returns the name of the box
func (b *Box) Name() string {
return b.name
}

View File

@ -1,39 +0,0 @@
package rice
// LocateMethod defines how a box is located.
type LocateMethod int
const (
LocateFS = LocateMethod(iota) // Locate on the filesystem according to package path.
LocateAppended // Locate boxes appended to the executable.
LocateEmbedded // Locate embedded boxes.
LocateWorkingDirectory // Locate on the binary working directory
)
// Config allows customizing the box lookup behavior.
type Config struct {
// LocateOrder defines the priority order that boxes are searched for. By
// default, the package global FindBox searches for embedded boxes first,
// then appended boxes, and then finally boxes on the filesystem. That
// search order may be customized by provided the ordered list here. Leaving
// out a particular method will omit that from the search space. For
// example, []LocateMethod{LocateEmbedded, LocateAppended} will never search
// the filesystem for boxes.
LocateOrder []LocateMethod
}
// FindBox searches for boxes using the LocateOrder of the config.
func (c *Config) FindBox(boxName string) (*Box, error) {
return findBox(boxName, c.LocateOrder)
}
// MustFindBox searches for boxes using the LocateOrder of the config, like
// FindBox does. It does not return an error, instead it panics when an error
// occurs.
func (c *Config) MustFindBox(boxName string) *Box {
box, err := findBox(boxName, c.LocateOrder)
if err != nil {
panic(err)
}
return box
}

View File

@ -1,4 +0,0 @@
package rice
// Debug can be set to true to enable debugging.
var Debug = false

View File

@ -1,90 +0,0 @@
package rice
import (
"os"
"time"
"github.com/GeertJohan/go.rice/embedded"
)
// re-type to make exported methods invisible to user (godoc)
// they're not required for the user
// embeddedDirInfo implements os.FileInfo
type embeddedDirInfo embedded.EmbeddedDir
// Name returns the base name of the directory
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) Name() string {
return ed.Filename
}
// Size always returns 0
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) Size() int64 {
return 0
}
// Mode returns the file mode bits
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) Mode() os.FileMode {
return os.FileMode(0555 | os.ModeDir) // dr-xr-xr-x
}
// ModTime returns the modification time
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) ModTime() time.Time {
return ed.DirModTime
}
// IsDir returns the abbreviation for Mode().IsDir() (always true)
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) IsDir() bool {
return true
}
// Sys returns the underlying data source (always nil)
// (implementing os.FileInfo)
func (ed *embeddedDirInfo) Sys() interface{} {
return nil
}
// re-type to make exported methods invisible to user (godoc)
// they're not required for the user
// embeddedFileInfo implements os.FileInfo
type embeddedFileInfo embedded.EmbeddedFile
// Name returns the base name of the file
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) Name() string {
return ef.Filename
}
// Size returns the length in bytes for regular files; system-dependent for others
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) Size() int64 {
return int64(len(ef.Content))
}
// Mode returns the file mode bits
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) Mode() os.FileMode {
return os.FileMode(0555) // r-xr-xr-x
}
// ModTime returns the modification time
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) ModTime() time.Time {
return ef.FileModTime
}
// IsDir returns the abbreviation for Mode().IsDir() (always false)
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) IsDir() bool {
return false
}
// Sys returns the underlying data source (always nil)
// (implementing os.FileInfo)
func (ef *embeddedFileInfo) Sys() interface{} {
return nil
}

View File

@ -1,23 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["embedded.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/GeertJohan/go.rice/embedded",
importpath = "github.com/GeertJohan/go.rice/embedded",
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,80 +0,0 @@
// Package embedded defines embedded data types that are shared between the go.rice package and generated code.
package embedded
import (
"fmt"
"path/filepath"
"strings"
"time"
)
const (
EmbedTypeGo = 0
EmbedTypeSyso = 1
)
// EmbeddedBox defines an embedded box
type EmbeddedBox struct {
Name string // box name
Time time.Time // embed time
EmbedType int // kind of embedding
Files map[string]*EmbeddedFile // ALL embedded files by full path
Dirs map[string]*EmbeddedDir // ALL embedded dirs by full path
}
// Link creates the ChildDirs and ChildFiles links in all EmbeddedDir's
func (e *EmbeddedBox) Link() {
for path, ed := range e.Dirs {
fmt.Println(path)
ed.ChildDirs = make([]*EmbeddedDir, 0)
ed.ChildFiles = make([]*EmbeddedFile, 0)
}
for path, ed := range e.Dirs {
parentDirpath, _ := filepath.Split(path)
if strings.HasSuffix(parentDirpath, "/") {
parentDirpath = parentDirpath[:len(parentDirpath)-1]
}
parentDir := e.Dirs[parentDirpath]
if parentDir == nil {
panic("parentDir `" + parentDirpath + "` is missing in embedded box")
}
parentDir.ChildDirs = append(parentDir.ChildDirs, ed)
}
for path, ef := range e.Files {
dirpath, _ := filepath.Split(path)
if strings.HasSuffix(dirpath, "/") {
dirpath = dirpath[:len(dirpath)-1]
}
dir := e.Dirs[dirpath]
if dir == nil {
panic("dir `" + dirpath + "` is missing in embedded box")
}
dir.ChildFiles = append(dir.ChildFiles, ef)
}
}
// EmbeddedDir is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
type EmbeddedDir struct {
Filename string
DirModTime time.Time
ChildDirs []*EmbeddedDir // direct childs, as returned by virtualDir.Readdir()
ChildFiles []*EmbeddedFile // direct childs, as returned by virtualDir.Readdir()
}
// EmbeddedFile is instanced in the code generated by the rice tool and contains all necicary information about an embedded file
type EmbeddedFile struct {
Filename string // filename
FileModTime time.Time
Content string
}
// EmbeddedBoxes is a public register of embedded boxes
var EmbeddedBoxes = make(map[string]*EmbeddedBox)
// RegisterEmbeddedBox registers an EmbeddedBox
func RegisterEmbeddedBox(name string, box *EmbeddedBox) {
if _, exists := EmbeddedBoxes[name]; exists {
panic(fmt.Sprintf("EmbeddedBox with name `%s` exists already", name))
}
EmbeddedBoxes[name] = box
}

View File

@ -1,144 +0,0 @@
package rice
import (
"bytes"
"errors"
"os"
"path/filepath"
)
// File implements the io.Reader, io.Seeker, io.Closer and http.File interfaces
type File struct {
// File abstracts file methods so the user doesn't see the difference between rice.virtualFile, rice.virtualDir and os.File
// TODO: maybe use internal File interface and four implementations: *os.File, appendedFile, virtualFile, virtualDir
// real file on disk
realF *os.File
// when embedded (go)
virtualF *virtualFile
virtualD *virtualDir
// when appended (zip)
appendedF *appendedFile
appendedFileReader *bytes.Reader
// TODO: is appendedFileReader subject of races? Might need a lock here..
}
// Close is like (*os.File).Close()
// Visit http://golang.org/pkg/os/#File.Close for more information
func (f *File) Close() error {
if f.appendedF != nil {
if f.appendedFileReader == nil {
return errors.New("already closed")
}
f.appendedFileReader = nil
return nil
}
if f.virtualF != nil {
return f.virtualF.close()
}
if f.virtualD != nil {
return f.virtualD.close()
}
return f.realF.Close()
}
// Stat is like (*os.File).Stat()
// Visit http://golang.org/pkg/os/#File.Stat for more information
func (f *File) Stat() (os.FileInfo, error) {
if f.appendedF != nil {
if f.appendedF.dir {
return f.appendedF.dirInfo, nil
}
if f.appendedFileReader == nil {
return nil, errors.New("file is closed")
}
return f.appendedF.zipFile.FileInfo(), nil
}
if f.virtualF != nil {
return f.virtualF.stat()
}
if f.virtualD != nil {
return f.virtualD.stat()
}
return f.realF.Stat()
}
// Readdir is like (*os.File).Readdir()
// Visit http://golang.org/pkg/os/#File.Readdir for more information
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
if f.appendedF != nil {
if f.appendedF.dir {
fi := make([]os.FileInfo, 0, len(f.appendedF.children))
for _, childAppendedFile := range f.appendedF.children {
if childAppendedFile.dir {
fi = append(fi, childAppendedFile.dirInfo)
} else {
fi = append(fi, childAppendedFile.zipFile.FileInfo())
}
}
return fi, nil
}
//++ TODO: is os.ErrInvalid the correct error for Readdir on file?
return nil, os.ErrInvalid
}
if f.virtualF != nil {
return f.virtualF.readdir(count)
}
if f.virtualD != nil {
return f.virtualD.readdir(count)
}
return f.realF.Readdir(count)
}
// Read is like (*os.File).Read()
// Visit http://golang.org/pkg/os/#File.Read for more information
func (f *File) Read(bts []byte) (int, error) {
if f.appendedF != nil {
if f.appendedFileReader == nil {
return 0, &os.PathError{
Op: "read",
Path: filepath.Base(f.appendedF.zipFile.Name),
Err: errors.New("file is closed"),
}
}
if f.appendedF.dir {
return 0, &os.PathError{
Op: "read",
Path: filepath.Base(f.appendedF.zipFile.Name),
Err: errors.New("is a directory"),
}
}
return f.appendedFileReader.Read(bts)
}
if f.virtualF != nil {
return f.virtualF.read(bts)
}
if f.virtualD != nil {
return f.virtualD.read(bts)
}
return f.realF.Read(bts)
}
// Seek is like (*os.File).Seek()
// Visit http://golang.org/pkg/os/#File.Seek for more information
func (f *File) Seek(offset int64, whence int) (int64, error) {
if f.appendedF != nil {
if f.appendedFileReader == nil {
return 0, &os.PathError{
Op: "seek",
Path: filepath.Base(f.appendedF.zipFile.Name),
Err: errors.New("file is closed"),
}
}
return f.appendedFileReader.Seek(offset, whence)
}
if f.virtualF != nil {
return f.virtualF.seek(offset, whence)
}
if f.virtualD != nil {
return f.virtualD.seek(offset, whence)
}
return f.realF.Seek(offset, whence)
}

View File

@ -1,21 +0,0 @@
package rice
import (
"net/http"
)
// HTTPBox implements http.FileSystem which allows the use of Box with a http.FileServer.
// e.g.: http.Handle("/", http.FileServer(rice.MustFindBox("http-files").HTTPBox()))
type HTTPBox struct {
*Box
}
// HTTPBox creates a new HTTPBox from an existing Box
func (b *Box) HTTPBox() *HTTPBox {
return &HTTPBox{b}
}
// Open returns a File using the http.File interface
func (hb *HTTPBox) Open(name string) (http.File, error) {
return hb.Box.Open(name)
}

View File

@ -1,19 +0,0 @@
package rice
import "os"
// SortByName allows an array of os.FileInfo objects
// to be easily sorted by filename using sort.Sort(SortByName(array))
type SortByName []os.FileInfo
func (f SortByName) Len() int { return len(f) }
func (f SortByName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
func (f SortByName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
// SortByModified allows an array of os.FileInfo objects
// to be easily sorted by modified date using sort.Sort(SortByModified(array))
type SortByModified []os.FileInfo
func (f SortByModified) Len() int { return len(f) }
func (f SortByModified) Less(i, j int) bool { return f[i].ModTime().Unix() > f[j].ModTime().Unix() }
func (f SortByModified) Swap(i, j int) { f[i], f[j] = f[j], f[i] }

View File

@ -1,252 +0,0 @@
package rice
import (
"errors"
"io"
"os"
"path/filepath"
"sort"
"github.com/GeertJohan/go.rice/embedded"
)
//++ TODO: IDEA: merge virtualFile and virtualDir, this decreases work done by rice.File
// Error indicating some function is not implemented yet (but available to satisfy an interface)
var ErrNotImplemented = errors.New("not implemented yet")
// virtualFile is a 'stateful' virtual file.
// virtualFile wraps an *EmbeddedFile for a call to Box.Open() and virtualizes 'read cursor' (offset) and 'closing'.
// virtualFile is only internally visible and should be exposed through rice.File
type virtualFile struct {
*embedded.EmbeddedFile // the actual embedded file, embedded to obtain methods
offset int64 // read position on the virtual file
closed bool // closed when true
}
// create a new virtualFile for given EmbeddedFile
func newVirtualFile(ef *embedded.EmbeddedFile) *virtualFile {
vf := &virtualFile{
EmbeddedFile: ef,
offset: 0,
closed: false,
}
return vf
}
//++ TODO check for nil pointers in all these methods. When so: return os.PathError with Err: os.ErrInvalid
func (vf *virtualFile) close() error {
if vf.closed {
return &os.PathError{
Op: "close",
Path: vf.EmbeddedFile.Filename,
Err: errors.New("already closed"),
}
}
vf.EmbeddedFile = nil
vf.closed = true
return nil
}
func (vf *virtualFile) stat() (os.FileInfo, error) {
if vf.closed {
return nil, &os.PathError{
Op: "stat",
Path: vf.EmbeddedFile.Filename,
Err: errors.New("bad file descriptor"),
}
}
return (*embeddedFileInfo)(vf.EmbeddedFile), nil
}
func (vf *virtualFile) readdir(count int) ([]os.FileInfo, error) {
if vf.closed {
return nil, &os.PathError{
Op: "readdir",
Path: vf.EmbeddedFile.Filename,
Err: errors.New("bad file descriptor"),
}
}
//TODO: return proper error for a readdir() call on a file
return nil, ErrNotImplemented
}
func (vf *virtualFile) read(bts []byte) (int, error) {
if vf.closed {
return 0, &os.PathError{
Op: "read",
Path: vf.EmbeddedFile.Filename,
Err: errors.New("bad file descriptor"),
}
}
end := vf.offset + int64(len(bts))
if end >= int64(len(vf.Content)) {
// end of file, so return what we have + EOF
n := copy(bts, vf.Content[vf.offset:])
vf.offset = 0
return n, io.EOF
}
n := copy(bts, vf.Content[vf.offset:end])
vf.offset += int64(n)
return n, nil
}
func (vf *virtualFile) seek(offset int64, whence int) (int64, error) {
if vf.closed {
return 0, &os.PathError{
Op: "seek",
Path: vf.EmbeddedFile.Filename,
Err: errors.New("bad file descriptor"),
}
}
var e error
//++ TODO: check if this is correct implementation for seek
switch whence {
case os.SEEK_SET:
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
vf.offset = offset
case os.SEEK_CUR:
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
vf.offset += offset
case os.SEEK_END:
//++ check if new offset isn't out of bounds, set e when it is, then break out of switch
vf.offset = int64(len(vf.EmbeddedFile.Content)) - offset
}
if e != nil {
return 0, &os.PathError{
Op: "seek",
Path: vf.Filename,
Err: e,
}
}
return vf.offset, nil
}
// virtualDir is a 'stateful' virtual directory.
// virtualDir wraps an *EmbeddedDir for a call to Box.Open() and virtualizes 'closing'.
// virtualDir is only internally visible and should be exposed through rice.File
type virtualDir struct {
*embedded.EmbeddedDir
offset int // readdir position on the directory
closed bool
}
// create a new virtualDir for given EmbeddedDir
func newVirtualDir(ed *embedded.EmbeddedDir) *virtualDir {
vd := &virtualDir{
EmbeddedDir: ed,
offset: 0,
closed: false,
}
return vd
}
func (vd *virtualDir) close() error {
//++ TODO: needs sync mutex?
if vd.closed {
return &os.PathError{
Op: "close",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("already closed"),
}
}
vd.closed = true
return nil
}
func (vd *virtualDir) stat() (os.FileInfo, error) {
if vd.closed {
return nil, &os.PathError{
Op: "stat",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("bad file descriptor"),
}
}
return (*embeddedDirInfo)(vd.EmbeddedDir), nil
}
func (vd *virtualDir) readdir(n int) (fi []os.FileInfo, err error) {
if vd.closed {
return nil, &os.PathError{
Op: "readdir",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("bad file descriptor"),
}
}
// Build up the array of our contents
var files []os.FileInfo
// Add the child directories
for _, child := range vd.ChildDirs {
child.Filename = filepath.Base(child.Filename)
files = append(files, (*embeddedDirInfo)(child))
}
// Add the child files
for _, child := range vd.ChildFiles {
child.Filename = filepath.Base(child.Filename)
files = append(files, (*embeddedFileInfo)(child))
}
// Sort it by filename (lexical order)
sort.Sort(SortByName(files))
// Return all contents if that's what is requested
if n <= 0 {
vd.offset = 0
return files, nil
}
// If user has requested past the end of our list
// return what we can and send an EOF
if vd.offset+n >= len(files) {
offset := vd.offset
vd.offset = 0
return files[offset:], io.EOF
}
offset := vd.offset
vd.offset += n
return files[offset : offset+n], nil
}
func (vd *virtualDir) read(bts []byte) (int, error) {
if vd.closed {
return 0, &os.PathError{
Op: "read",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("bad file descriptor"),
}
}
return 0, &os.PathError{
Op: "read",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("is a directory"),
}
}
func (vd *virtualDir) seek(offset int64, whence int) (int64, error) {
if vd.closed {
return 0, &os.PathError{
Op: "seek",
Path: vd.EmbeddedDir.Filename,
Err: errors.New("bad file descriptor"),
}
}
return 0, &os.PathError{
Op: "seek",
Path: vd.Filename,
Err: errors.New("is a directory"),
}
}

View File

@ -1,122 +0,0 @@
package rice
import (
"os"
"path/filepath"
"sort"
"strings"
)
// Walk is like filepath.Walk()
// Visit http://golang.org/pkg/path/filepath/#Walk for more information
func (b *Box) Walk(path string, walkFn filepath.WalkFunc) error {
pathFile, err := b.Open(path)
if err != nil {
return err
}
defer pathFile.Close()
pathInfo, err := pathFile.Stat()
if err != nil {
return err
}
if b.IsAppended() || b.IsEmbedded() {
return b.walk(path, pathInfo, walkFn)
}
// We don't have any embedded or appended box so use live filesystem mode
return filepath.Walk(b.absolutePath+string(os.PathSeparator)+path, func(path string, info os.FileInfo, err error) error {
// Strip out the box name from the returned paths
path = strings.TrimPrefix(path, b.absolutePath+string(os.PathSeparator))
return walkFn(path, info, err)
})
}
// walk recursively descends path.
// See walk() in $GOROOT/src/pkg/path/filepath/path.go
func (b *Box) walk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error {
err := walkFn(path, info, nil)
if err != nil {
if info.IsDir() && err == filepath.SkipDir {
return nil
}
return err
}
if !info.IsDir() {
return nil
}
names, err := b.readDirNames(path)
if err != nil {
return walkFn(path, info, err)
}
for _, name := range names {
filename := filepath.Join(path, name)
fileObject, err := b.Open(filename)
if err != nil {
return err
}
defer fileObject.Close()
fileInfo, err := fileObject.Stat()
if err != nil {
if err := walkFn(filename, fileInfo, err); err != nil && err != filepath.SkipDir {
return err
}
} else {
err = b.walk(filename, fileInfo, walkFn)
if err != nil {
if !fileInfo.IsDir() || err != filepath.SkipDir {
return err
}
}
}
}
return nil
}
// readDirNames reads the directory named by path and returns a sorted list of directory entries.
// See readDirNames() in $GOROOT/pkg/path/filepath/path.go
func (b *Box) readDirNames(path string) ([]string, error) {
f, err := b.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return nil, err
}
if !stat.IsDir() {
return nil, nil
}
infos, err := f.Readdir(0)
if err != nil {
return nil, err
}
var names []string
for _, info := range infos {
names = append(names, info.Name())
}
sort.Strings(names)
return names, nil
}

View File

@ -1,42 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["api.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api",
importpath = "github.com/cloudflare/cfssl/api",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/cloudflare/cfssl/api/bundle:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/certinfo:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/client:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/crl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/gencrl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/generator:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/health:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/info:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/initca:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/ocsp:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/revoke:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/scan:all-srcs",
"//vendor/github.com/cloudflare/cfssl/api/signhandler:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,231 +0,0 @@
// Package api implements an HTTP-based API and server for CFSSL.
package api
import (
"encoding/json"
"io/ioutil"
"net/http"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
)
// Handler is an interface providing a generic mechanism for handling HTTP requests.
type Handler interface {
Handle(w http.ResponseWriter, r *http.Request) error
}
// HTTPHandler is a wrapper that encapsulates Handler interface as http.Handler.
// HTTPHandler also enforces that the Handler only responds to requests with registered HTTP methods.
type HTTPHandler struct {
Handler // CFSSL handler
Methods []string // The associated HTTP methods
}
// HandlerFunc is similar to the http.HandlerFunc type; it serves as
// an adapter allowing the use of ordinary functions as Handlers. If
// f is a function with the appropriate signature, HandlerFunc(f) is a
// Handler object that calls f.
type HandlerFunc func(http.ResponseWriter, *http.Request) error
// Handle calls f(w, r)
func (f HandlerFunc) Handle(w http.ResponseWriter, r *http.Request) error {
w.Header().Set("Content-Type", "application/json")
return f(w, r)
}
// HandleError is the centralised error handling and reporting.
func HandleError(w http.ResponseWriter, err error) (code int) {
if err == nil {
return http.StatusOK
}
msg := err.Error()
httpCode := http.StatusInternalServerError
// If it is recognized as HttpError emitted from cfssl,
// we rewrite the status code accordingly. If it is a
// cfssl error, set the http status to StatusBadRequest
switch err := err.(type) {
case *errors.HTTPError:
httpCode = err.StatusCode
code = err.StatusCode
case *errors.Error:
httpCode = http.StatusBadRequest
code = err.ErrorCode
msg = err.Message
}
response := NewErrorResponse(msg, code)
jsonMessage, err := json.Marshal(response)
if err != nil {
log.Errorf("Failed to marshal JSON: %v", err)
} else {
msg = string(jsonMessage)
}
http.Error(w, msg, httpCode)
return code
}
// ServeHTTP encapsulates the call to underlying Handler to handle the request
// and return the response with proper HTTP status code
func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var err error
var match bool
// Throw 405 when requested with an unsupported verb.
for _, m := range h.Methods {
if m == r.Method {
match = true
}
}
if match {
err = h.Handle(w, r)
} else {
err = errors.NewMethodNotAllowed(r.Method)
}
status := HandleError(w, err)
log.Infof("%s - \"%s %s\" %d", r.RemoteAddr, r.Method, r.URL, status)
}
// readRequestBlob takes a JSON-blob-encoded response body in the form
// map[string]string and returns it, the list of keywords presented,
// and any error that occurred.
func readRequestBlob(r *http.Request) (map[string]string, error) {
var blob map[string]string
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
r.Body.Close()
err = json.Unmarshal(body, &blob)
if err != nil {
return nil, err
}
return blob, nil
}
// ProcessRequestOneOf reads a JSON blob for the request and makes
// sure it contains one of a set of keywords. For example, a request
// might have the ('foo' && 'bar') keys, OR it might have the 'baz'
// key. In either case, we want to accept the request; however, if
// none of these sets shows up, the request is a bad request, and it
// should be returned.
func ProcessRequestOneOf(r *http.Request, keywordSets [][]string) (map[string]string, []string, error) {
blob, err := readRequestBlob(r)
if err != nil {
return nil, nil, err
}
var matched []string
for _, set := range keywordSets {
if matchKeywords(blob, set) {
if matched != nil {
return nil, nil, errors.NewBadRequestString("mismatched parameters")
}
matched = set
}
}
if matched == nil {
return nil, nil, errors.NewBadRequestString("no valid parameter sets found")
}
return blob, matched, nil
}
// ProcessRequestFirstMatchOf reads a JSON blob for the request and returns
// the first match of a set of keywords. For example, a request
// might have one of the following combinations: (foo=1, bar=2), (foo=1), and (bar=2)
// By giving a specific ordering of those combinations, we could decide how to accept
// the request.
func ProcessRequestFirstMatchOf(r *http.Request, keywordSets [][]string) (map[string]string, []string, error) {
blob, err := readRequestBlob(r)
if err != nil {
return nil, nil, err
}
for _, set := range keywordSets {
if matchKeywords(blob, set) {
return blob, set, nil
}
}
return nil, nil, errors.NewBadRequestString("no valid parameter sets found")
}
func matchKeywords(blob map[string]string, keywords []string) bool {
for _, keyword := range keywords {
if _, ok := blob[keyword]; !ok {
return false
}
}
return true
}
// ResponseMessage implements the standard for response errors and
// messages. A message has a code and a string message.
type ResponseMessage struct {
Code int `json:"code"`
Message string `json:"message"`
}
// Response implements the CloudFlare standard for API
// responses.
type Response struct {
Success bool `json:"success"`
Result interface{} `json:"result"`
Errors []ResponseMessage `json:"errors"`
Messages []ResponseMessage `json:"messages"`
}
// NewSuccessResponse is a shortcut for creating new successul API
// responses.
func NewSuccessResponse(result interface{}) Response {
return Response{
Success: true,
Result: result,
Errors: []ResponseMessage{},
Messages: []ResponseMessage{},
}
}
// NewSuccessResponseWithMessage is a shortcut for creating new successul API
// responses that includes a message.
func NewSuccessResponseWithMessage(result interface{}, message string, code int) Response {
return Response{
Success: true,
Result: result,
Errors: []ResponseMessage{},
Messages: []ResponseMessage{{code, message}},
}
}
// NewErrorResponse is a shortcut for creating an error response for a
// single error.
func NewErrorResponse(message string, code int) Response {
return Response{
Success: false,
Result: nil,
Errors: []ResponseMessage{{code, message}},
Messages: []ResponseMessage{},
}
}
// SendResponse builds a response from the result, sets the JSON
// header, and writes to the http.ResponseWriter.
func SendResponse(w http.ResponseWriter, result interface{}) error {
response := NewSuccessResponse(result)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
err := enc.Encode(response)
return err
}
// SendResponseWithMessage builds a response from the result and the
// provided message, sets the JSON header, and writes to the
// http.ResponseWriter.
func SendResponseWithMessage(w http.ResponseWriter, result interface{}, message string, code int) error {
response := NewSuccessResponseWithMessage(result, message, code)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
err := enc.Encode(response)
return err
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["bundle.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/bundle",
importpath = "github.com/cloudflare/cfssl/api/bundle",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/bundler:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,91 +0,0 @@
// Package bundle implements the HTTP handler for the bundle command.
package bundle
import (
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/bundler"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
)
// Handler accepts requests for either remote or uploaded
// certificates to be bundled, and returns a certificate bundle (or
// error).
type Handler struct {
bundler *bundler.Bundler
}
// NewHandler creates a new bundler that uses the root bundle and
// intermediate bundle in the trust chain.
func NewHandler(caBundleFile, intBundleFile string) (http.Handler, error) {
var err error
b := new(Handler)
if b.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile); err != nil {
return nil, err
}
log.Info("bundler API ready")
return api.HTTPHandler{Handler: b, Methods: []string{"POST"}}, nil
}
// Handle implements an http.Handler interface for the bundle handler.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
blob, matched, err := api.ProcessRequestFirstMatchOf(r,
[][]string{
{"certificate"},
{"domain"},
})
if err != nil {
log.Warningf("invalid request: %v", err)
return err
}
flavor := blob["flavor"]
bf := bundler.Ubiquitous
if flavor != "" {
bf = bundler.BundleFlavor(flavor)
}
log.Infof("request for flavor %v", bf)
var result *bundler.Bundle
switch matched[0] {
case "domain":
bundle, err := h.bundler.BundleFromRemote(blob["domain"], blob["ip"], bf)
if err != nil {
log.Warningf("couldn't bundle from remote: %v", err)
return err
}
result = bundle
case "certificate":
bundle, err := h.bundler.BundleFromPEMorDER([]byte(blob["certificate"]), []byte(blob["private_key"]), bf, "")
if err != nil {
log.Warning("bad PEM certifcate or private key")
return err
}
serverName := blob["domain"]
ip := blob["ip"]
if serverName != "" {
err := bundle.Cert.VerifyHostname(serverName)
if err != nil {
return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
}
if ip != "" {
err := bundle.Cert.VerifyHostname(ip)
if err != nil {
return errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
}
result = bundle
}
log.Info("wrote response")
return api.SendResponse(w, result)
}

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["certinfo.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/certinfo",
importpath = "github.com/cloudflare/cfssl/api/certinfo",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certinfo:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,50 +0,0 @@
// Package certinfo implements the HTTP handler for the certinfo command.
package certinfo
import (
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/certinfo"
"github.com/cloudflare/cfssl/log"
)
// Handler accepts requests for either remote or uploaded
// certificates to be bundled, and returns a certificate bundle (or
// error).
type Handler struct{}
// NewHandler creates a new bundler that uses the root bundle and
// intermediate bundle in the trust chain.
func NewHandler() http.Handler {
return api.HTTPHandler{Handler: new(Handler), Methods: []string{"POST"}}
}
// Handle implements an http.Handler interface for the bundle handler.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) (err error) {
blob, matched, err := api.ProcessRequestFirstMatchOf(r,
[][]string{
{"certificate"},
{"domain"},
})
if err != nil {
log.Warningf("invalid request: %v", err)
return err
}
var cert *certinfo.Certificate
switch matched[0] {
case "domain":
if cert, err = certinfo.ParseCertificateDomain(blob["domain"]); err != nil {
log.Warningf("couldn't parse remote certificate: %v", err)
return err
}
case "certificate":
if cert, err = certinfo.ParseCertificatePEM([]byte(blob["certificate"])); err != nil {
log.Warningf("bad PEM certifcate: %v", err)
return err
}
}
return api.SendResponse(w, cert)
}

View File

@ -1,34 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"client.go",
"group.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/client",
importpath = "github.com/cloudflare/cfssl/api/client",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/auth:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/info:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,6 +0,0 @@
package client
// SignResult is the result of signing a CSR.
type SignResult struct {
Certificate []byte `json:"certificate"`
}

View File

@ -1,370 +0,0 @@
// Package client implements a Go client for CFSSL API commands.
package client
import (
"bytes"
"crypto/tls"
"encoding/json"
stderr "errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/auth"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/info"
"github.com/cloudflare/cfssl/log"
)
// A server points to a single remote CFSSL instance.
type server struct {
URL string
TLSConfig *tls.Config
reqModifier func(*http.Request, []byte)
RequestTimeout time.Duration
proxy func(*http.Request) (*url.URL, error)
}
// A Remote points to at least one (but possibly multiple) remote
// CFSSL instances. It must be able to perform a authenticated and
// unauthenticated certificate signing requests, return information
// about the CA on the other end, and return a list of the hosts that
// are used by the remote.
type Remote interface {
AuthSign(req, id []byte, provider auth.Provider) ([]byte, error)
Sign(jsonData []byte) ([]byte, error)
Info(jsonData []byte) (*info.Resp, error)
Hosts() []string
SetReqModifier(func(*http.Request, []byte))
SetRequestTimeout(d time.Duration)
SetProxy(func(*http.Request) (*url.URL, error))
}
// NewServer sets up a new server target. The address should be of
// The format [protocol:]name[:port] of the remote CFSSL instance.
// If no protocol is given http is default. If no port
// is specified, the CFSSL default port (8888) is used. If the name is
// a comma-separated list of hosts, an ordered group will be returned.
func NewServer(addr string) Remote {
return NewServerTLS(addr, nil)
}
// NewServerTLS is the TLS version of NewServer
func NewServerTLS(addr string, tlsConfig *tls.Config) Remote {
addrs := strings.Split(addr, ",")
var remote Remote
if len(addrs) > 1 {
remote, _ = NewGroup(addrs, tlsConfig, StrategyOrderedList)
} else {
u, err := normalizeURL(addrs[0])
if err != nil {
log.Errorf("bad url: %v", err)
return nil
}
srv := newServer(u, tlsConfig)
if srv != nil {
remote = srv
}
}
return remote
}
func (srv *server) Hosts() []string {
return []string{srv.URL}
}
func (srv *server) SetReqModifier(mod func(*http.Request, []byte)) {
srv.reqModifier = mod
}
func (srv *server) SetRequestTimeout(timeout time.Duration) {
srv.RequestTimeout = timeout
}
func (srv *server) SetProxy(proxy func(*http.Request) (*url.URL, error)) {
srv.proxy = proxy
}
func newServer(u *url.URL, tlsConfig *tls.Config) *server {
URL := u.String()
return &server{
URL: URL,
TLSConfig: tlsConfig,
}
}
func (srv *server) getURL(endpoint string) string {
return fmt.Sprintf("%s/api/v1/cfssl/%s", srv.URL, endpoint)
}
func (srv *server) createTransport() *http.Transport {
// Start with defaults from http.DefaultTransport
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
// Setup HTTPS client
tlsConfig := srv.TLSConfig
tlsConfig.BuildNameToCertificate()
transport.TLSClientConfig = tlsConfig
// Setup Proxy
if srv.proxy != nil {
transport.Proxy = srv.proxy
}
return transport
}
// post connects to the remote server and returns a Response struct
func (srv *server) post(url string, jsonData []byte) (*api.Response, error) {
var resp *http.Response
var err error
client := &http.Client{}
if srv.TLSConfig != nil {
client.Transport = srv.createTransport()
}
if srv.RequestTimeout != 0 {
client.Timeout = srv.RequestTimeout
}
req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
if err != nil {
err = fmt.Errorf("failed POST to %s: %v", url, err)
return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
}
req.Close = true
req.Header.Set("content-type", "application/json")
if srv.reqModifier != nil {
srv.reqModifier(req, jsonData)
}
resp, err = client.Do(req)
if err != nil {
err = fmt.Errorf("failed POST to %s: %v", url, err)
return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, err)
}
defer req.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(errors.APIClientError, errors.IOError, err)
}
if resp.StatusCode != http.StatusOK {
log.Errorf("http error with %s", url)
return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New(string(body)))
}
var response api.Response
err = json.Unmarshal(body, &response)
if err != nil {
log.Debug("Unable to parse response body:", string(body))
return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err)
}
if !response.Success || response.Result == nil {
if len(response.Errors) > 0 {
return nil, errors.Wrap(errors.APIClientError, errors.ServerRequestFailed, stderr.New(response.Errors[0].Message))
}
return nil, errors.New(errors.APIClientError, errors.ServerRequestFailed)
}
return &response, nil
}
// AuthSign fills out an authenticated signing request to the server,
// receiving a certificate or error in response.
// It takes the serialized JSON request to send, remote address and
// authentication provider.
func (srv *server) AuthSign(req, id []byte, provider auth.Provider) ([]byte, error) {
return srv.authReq(req, id, provider, "sign")
}
// AuthInfo fills out an authenticated info request to the server,
// receiving a certificate or error in response.
// It takes the serialized JSON request to send, remote address and
// authentication provider.
func (srv *server) AuthInfo(req, id []byte, provider auth.Provider) ([]byte, error) {
return srv.authReq(req, id, provider, "info")
}
// authReq is the common logic for AuthSign and AuthInfo -- perform the given
// request, and return the resultant certificate.
// The target is either 'sign' or 'info'.
func (srv *server) authReq(req, ID []byte, provider auth.Provider, target string) ([]byte, error) {
url := srv.getURL("auth" + target)
token, err := provider.Token(req)
if err != nil {
return nil, errors.Wrap(errors.APIClientError, errors.AuthenticationFailure, err)
}
aReq := &auth.AuthenticatedRequest{
Timestamp: time.Now().Unix(),
RemoteAddress: ID,
Token: token,
Request: req,
}
jsonData, err := json.Marshal(aReq)
if err != nil {
return nil, errors.Wrap(errors.APIClientError, errors.JSONError, err)
}
response, err := srv.post(url, jsonData)
if err != nil {
return nil, err
}
result, ok := response.Result.(map[string]interface{})
if !ok {
return nil, errors.New(errors.APIClientError, errors.JSONError)
}
cert, ok := result["certificate"].(string)
if !ok {
return nil, errors.New(errors.APIClientError, errors.JSONError)
}
return []byte(cert), nil
}
// Sign sends a signature request to the remote CFSSL server,
// receiving a signed certificate or an error in response.
// It takes the serialized JSON request to send.
func (srv *server) Sign(jsonData []byte) ([]byte, error) {
return srv.request(jsonData, "sign")
}
// Info sends an info request to the remote CFSSL server, receiving a
// response or an error in response.
// It takes the serialized JSON request to send.
func (srv *server) Info(jsonData []byte) (*info.Resp, error) {
res, err := srv.getResultMap(jsonData, "info")
if err != nil {
return nil, err
}
info := new(info.Resp)
if val, ok := res["certificate"]; ok {
info.Certificate = val.(string)
}
var usages []interface{}
if val, ok := res["usages"]; ok && val != nil {
usages = val.([]interface{})
}
if val, ok := res["expiry"]; ok && val != nil {
info.ExpiryString = val.(string)
}
info.Usage = make([]string, len(usages))
for i, s := range usages {
info.Usage[i] = s.(string)
}
return info, nil
}
func (srv *server) getResultMap(jsonData []byte, target string) (result map[string]interface{}, err error) {
url := srv.getURL(target)
response, err := srv.post(url, jsonData)
if err != nil {
return
}
result, ok := response.Result.(map[string]interface{})
if !ok {
err = errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New("response is formatted improperly"))
return
}
return
}
// request performs the common logic for Sign and Info, performing the actual
// request and returning the resultant certificate.
func (srv *server) request(jsonData []byte, target string) ([]byte, error) {
result, err := srv.getResultMap(jsonData, target)
if err != nil {
return nil, err
}
cert := result["certificate"].(string)
if cert != "" {
return []byte(cert), nil
}
return nil, errors.Wrap(errors.APIClientError, errors.ClientHTTPError, stderr.New("response doesn't contain certificate."))
}
// AuthRemote acts as a Remote with a default Provider for AuthSign.
type AuthRemote struct {
Remote
provider auth.Provider
}
// NewAuthServer sets up a new auth server target with an addr
// in the same format at NewServer and a default authentication provider to
// use for Sign requests.
func NewAuthServer(addr string, tlsConfig *tls.Config, provider auth.Provider) *AuthRemote {
return &AuthRemote{
Remote: NewServerTLS(addr, tlsConfig),
provider: provider,
}
}
// Sign is overloaded to perform an AuthSign request using the default auth provider.
func (ar *AuthRemote) Sign(req []byte) ([]byte, error) {
return ar.AuthSign(req, nil, ar.provider)
}
// nomalizeURL checks for http/https protocol, appends "http" as default protocol if not defiend in url
func normalizeURL(addr string) (*url.URL, error) {
addr = strings.TrimSpace(addr)
u, err := url.Parse(addr)
if err != nil {
return nil, err
}
if u.Opaque != "" {
u.Host = net.JoinHostPort(u.Scheme, u.Opaque)
u.Opaque = ""
} else if u.Path != "" && !strings.Contains(u.Path, ":") {
u.Host = net.JoinHostPort(u.Path, "8888")
u.Path = ""
} else if u.Scheme == "" {
u.Host = u.Path
u.Path = ""
}
if u.Scheme != "https" {
u.Scheme = "http"
}
_, port, err := net.SplitHostPort(u.Host)
if err != nil {
_, port, err = net.SplitHostPort(u.Host + ":8888")
if err != nil {
return nil, err
}
}
if port != "" {
_, err = strconv.Atoi(port)
if err != nil {
return nil, err
}
}
return u, nil
}

View File

@ -1,132 +0,0 @@
package client
import (
"crypto/tls"
"errors"
"net/http"
"net/url"
"strings"
"time"
"github.com/cloudflare/cfssl/auth"
"github.com/cloudflare/cfssl/info"
)
// Strategy is the means by which the server to use as a remote should
// be selected.
type Strategy int
const (
// StrategyInvalid indicates any strategy that is unsupported
// or returned when no strategy is applicable.
StrategyInvalid = iota
// StrategyOrderedList is a sequential list of servers: if the
// first server cannot be reached, the next is used. The
// client will proceed in this manner until the list of
// servers is exhausted, and then an error is returned.
StrategyOrderedList
)
var strategyStrings = map[string]Strategy{
"ordered_list": StrategyOrderedList,
}
// StrategyFromString takes a string describing a
func StrategyFromString(s string) Strategy {
s = strings.TrimSpace(strings.ToLower(s))
strategy, ok := strategyStrings[s]
if !ok {
return StrategyInvalid
}
return strategy
}
// NewGroup will use the collection of remotes specified with the
// given strategy.
func NewGroup(remotes []string, tlsConfig *tls.Config, strategy Strategy) (Remote, error) {
var servers = make([]*server, len(remotes))
for i := range remotes {
u, err := normalizeURL(remotes[i])
if err != nil {
return nil, err
}
servers[i] = newServer(u, tlsConfig)
}
switch strategy {
case StrategyOrderedList:
return newOrdererdListGroup(servers)
default:
return nil, errors.New("unrecognised strategy")
}
}
type orderedListGroup struct {
remotes []*server
}
func (g *orderedListGroup) Hosts() []string {
var hosts = make([]string, 0, len(g.remotes))
for _, srv := range g.remotes {
srvHosts := srv.Hosts()
hosts = append(hosts, srvHosts[0])
}
return hosts
}
func (g *orderedListGroup) SetRequestTimeout(timeout time.Duration) {
for _, srv := range g.remotes {
srv.SetRequestTimeout(timeout)
}
}
func (g *orderedListGroup) SetProxy(proxy func(*http.Request) (*url.URL, error)) {
for _, srv := range g.remotes {
srv.SetProxy(proxy)
}
}
func newOrdererdListGroup(remotes []*server) (Remote, error) {
return &orderedListGroup{
remotes: remotes,
}, nil
}
func (g *orderedListGroup) AuthSign(req, id []byte, provider auth.Provider) (resp []byte, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].AuthSign(req, id, provider)
if err == nil {
return resp, nil
}
}
return nil, err
}
func (g *orderedListGroup) Sign(jsonData []byte) (resp []byte, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].Sign(jsonData)
if err == nil {
return resp, nil
}
}
return nil, err
}
func (g *orderedListGroup) Info(jsonData []byte) (resp *info.Resp, err error) {
for i := range g.remotes {
resp, err = g.remotes[i].Info(jsonData)
if err == nil {
return resp, nil
}
}
return nil, err
}
// SetReqModifier does nothing because there is no request modifier for group
func (g *orderedListGroup) SetReqModifier(mod func(*http.Request, []byte)) {
// noop
}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["crl.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/crl",
importpath = "github.com/cloudflare/cfssl/api/crl",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb:go_default_library",
"//vendor/github.com/cloudflare/cfssl/crl:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,93 +0,0 @@
// Package crl implements the HTTP handler for the crl command.
package crl
import (
"crypto"
"crypto/x509"
"net/http"
"os"
"time"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/crl"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
)
// A Handler accepts requests with a serial number parameter
// and revokes
type Handler struct {
dbAccessor certdb.Accessor
ca *x509.Certificate
key crypto.Signer
}
// NewHandler returns a new http.Handler that handles a revoke request.
func NewHandler(dbAccessor certdb.Accessor, caPath string, caKeyPath string) (http.Handler, error) {
ca, err := helpers.ReadBytes(caPath)
if err != nil {
return nil, err
}
caKey, err := helpers.ReadBytes(caKeyPath)
if err != nil {
return nil, errors.Wrap(errors.PrivateKeyError, errors.ReadFailed, err)
}
// Parse the PEM encoded certificate
issuerCert, err := helpers.ParseCertificatePEM(ca)
if err != nil {
return nil, err
}
strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
password := []byte(strPassword)
if strPassword == "" {
password = nil
}
// Parse the key given
key, err := helpers.ParsePrivateKeyPEMWithPassword(caKey, password)
if err != nil {
log.Debug("malformed private key %v", err)
return nil, err
}
return &api.HTTPHandler{
Handler: &Handler{
dbAccessor: dbAccessor,
ca: issuerCert,
key: key,
},
Methods: []string{"GET"},
}, nil
}
// Handle responds to revocation requests. It attempts to revoke
// a certificate with a given serial number
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
var newExpiryTime = 7 * helpers.OneDay
certs, err := h.dbAccessor.GetRevokedAndUnexpiredCertificates()
if err != nil {
return err
}
queryExpiryTime := r.URL.Query().Get("expiry")
if queryExpiryTime != "" {
log.Infof("requested expiry time of %s", queryExpiryTime)
newExpiryTime, err = time.ParseDuration(queryExpiryTime)
if err != nil {
return err
}
}
result, err := crl.NewCRLFromDB(certs, h.ca, h.key, newExpiryTime)
if err != nil {
return err
}
return api.SendResponse(w, result)
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gencrl.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/gencrl",
importpath = "github.com/cloudflare/cfssl/api/gencrl",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,102 +0,0 @@
// Package gencrl implements the HTTP handler for the gencrl commands.
package gencrl
import (
"crypto/rand"
"crypto/x509/pkix"
"encoding/json"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"io/ioutil"
"math/big"
"net/http"
"strconv"
"strings"
"time"
)
// This type is meant to be unmarshalled from JSON
type jsonCRLRequest struct {
Certificate string `json:"certificate"`
SerialNumber []string `json:"serialNumber"`
PrivateKey string `json:"issuingKey"`
ExpiryTime string `json:"expireTime"`
}
// Handle responds to requests for crl generation. It creates this crl
// based off of the given certificate, serial numbers, and private key
func gencrlHandler(w http.ResponseWriter, r *http.Request) error {
var revokedCerts []pkix.RevokedCertificate
var oneWeek = time.Duration(604800) * time.Second
var newExpiryTime = time.Now()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
r.Body.Close()
req := &jsonCRLRequest{}
err = json.Unmarshal(body, req)
if err != nil {
log.Error(err)
}
if req.ExpiryTime != "" {
expiryTime := strings.TrimSpace(req.ExpiryTime)
expiryInt, err := strconv.ParseInt(expiryTime, 0, 32)
if err != nil {
return err
}
newExpiryTime = time.Now().Add((time.Duration(expiryInt) * time.Second))
}
if req.ExpiryTime == "" {
newExpiryTime = time.Now().Add(oneWeek)
}
if err != nil {
return err
}
cert, err := helpers.ParseCertificatePEM([]byte(req.Certificate))
if err != nil {
log.Error("error from ParseCertificatePEM", err)
return errors.NewBadRequestString("malformed certificate")
}
for _, value := range req.SerialNumber {
tempBigInt := new(big.Int)
tempBigInt.SetString(value, 10)
tempCert := pkix.RevokedCertificate{
SerialNumber: tempBigInt,
RevocationTime: time.Now(),
}
revokedCerts = append(revokedCerts, tempCert)
}
key, err := helpers.ParsePrivateKeyPEM([]byte(req.PrivateKey))
if err != nil {
log.Debug("malformed private key %v", err)
return errors.NewBadRequestString("malformed Private Key")
}
result, err := cert.CreateCRL(rand.Reader, key, revokedCerts, time.Now(), newExpiryTime)
if err != nil {
log.Debug("unable to create CRL: %v", err)
return err
}
return api.SendResponse(w, result)
}
// NewHandler returns a new http.Handler that handles a crl generation request.
func NewHandler() http.Handler {
return api.HTTPHandler{
Handler: api.HandlerFunc(gencrlHandler),
Methods: []string{"POST"},
}
}

View File

@ -1,33 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["generator.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/generator",
importpath = "github.com/cloudflare/cfssl/api/generator",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/bundler:go_default_library",
"//vendor/github.com/cloudflare/cfssl/config:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer/universal:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,319 +0,0 @@
// Package generator implements the HTTP handlers for certificate generation.
package generator
import (
"crypto/md5"
"crypto/sha1"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/bundler"
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
"github.com/cloudflare/cfssl/signer/universal"
)
const (
// CSRNoHostMessage is used to alert the user to a certificate lacking a hosts field.
CSRNoHostMessage = `This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").`
// NoBundlerMessage is used to alert the user that the server does not have a bundler initialized.
NoBundlerMessage = `This request requires a bundler, but one is not initialized for the API server.`
)
// Sum contains digests for a certificate or certificate request.
type Sum struct {
MD5 string `json:"md5"`
SHA1 string `json:"sha-1"`
}
// Validator is a type of function that contains the logic for validating
// a certificate request.
type Validator func(*csr.CertificateRequest) error
// A CertRequest stores a PEM-encoded private key and corresponding
// CSR; this is returned from the CSR generation endpoint.
type CertRequest struct {
Key string `json:"private_key"`
CSR string `json:"certificate_request"`
Sums map[string]Sum `json:"sums"`
}
// A Handler accepts JSON-encoded certificate requests and
// returns a new private key and certificate request.
type Handler struct {
generator *csr.Generator
}
// NewHandler builds a new Handler from the
// validation function provided.
func NewHandler(validator Validator) (http.Handler, error) {
log.Info("setting up key / CSR generator")
return &api.HTTPHandler{
Handler: &Handler{
generator: &csr.Generator{Validator: validator},
},
Methods: []string{"POST"},
}, nil
}
func computeSum(in []byte) (sum Sum, err error) {
var data []byte
p, _ := pem.Decode(in)
if p == nil {
err = errors.NewBadRequestString("not a CSR or certificate")
return
}
switch p.Type {
case "CERTIFICATE REQUEST":
var req *x509.CertificateRequest
req, err = x509.ParseCertificateRequest(p.Bytes)
if err != nil {
return
}
data = req.Raw
case "CERTIFICATE":
var cert *x509.Certificate
cert, err = x509.ParseCertificate(p.Bytes)
if err != nil {
return
}
data = cert.Raw
default:
err = errors.NewBadRequestString("not a CSR or certificate")
return
}
md5Sum := md5.Sum(data)
sha1Sum := sha1.Sum(data)
sum.MD5 = fmt.Sprintf("%X", md5Sum[:])
sum.SHA1 = fmt.Sprintf("%X", sha1Sum[:])
return
}
// Handle responds to requests for the CA to generate a new private
// key and certificate request on behalf of the client. The format for
// these requests is documented in the API documentation.
func (g *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
log.Info("request for CSR")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
return errors.NewBadRequest(err)
}
r.Body.Close()
req := new(csr.CertificateRequest)
req.KeyRequest = csr.NewBasicKeyRequest()
err = json.Unmarshal(body, req)
if err != nil {
log.Warningf("failed to unmarshal request: %v", err)
return errors.NewBadRequest(err)
}
if req.CA != nil {
log.Warningf("request received with CA section")
return errors.NewBadRequestString("ca section only permitted in initca")
}
csr, key, err := g.generator.ProcessRequest(req)
if err != nil {
log.Warningf("failed to process CSR: %v", err)
// The validator returns a *cfssl/errors.HttpError
return err
}
sum, err := computeSum(csr)
if err != nil {
return errors.NewBadRequest(err)
}
// Both key and csr are returned PEM-encoded.
response := api.NewSuccessResponse(&CertRequest{
Key: string(key),
CSR: string(csr),
Sums: map[string]Sum{"certificate_request": sum},
})
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
err = enc.Encode(response)
return err
}
// A CertGeneratorHandler accepts JSON-encoded certificate requests
// and returns a new private key and signed certificate; it handles
// sending the CSR to the server.
type CertGeneratorHandler struct {
generator *csr.Generator
bundler *bundler.Bundler
signer signer.Signer
}
// NewCertGeneratorHandler builds a new handler for generating
// certificates directly from certificate requests; the validator covers
// the certificate request and the CA's key and certificate are used to
// sign the generated request. If remote is not an empty string, the
// handler will send signature requests to the CFSSL instance contained
// in remote.
func NewCertGeneratorHandler(validator Validator, caFile, caKeyFile string, policy *config.Signing) (http.Handler, error) {
var err error
log.Info("setting up new generator / signer")
cg := new(CertGeneratorHandler)
if policy == nil {
policy = &config.Signing{
Default: config.DefaultConfig(),
Profiles: nil,
}
}
root := universal.Root{
Config: map[string]string{
"ca-file": caFile,
"ca-key-file": caKeyFile,
},
}
if cg.signer, err = universal.NewSigner(root, policy); err != nil {
log.Errorf("setting up signer failed: %v", err)
return nil, err
}
cg.generator = &csr.Generator{Validator: validator}
return api.HTTPHandler{Handler: cg, Methods: []string{"POST"}}, nil
}
// NewCertGeneratorHandlerFromSigner returns a handler directly from
// the signer and validation function.
func NewCertGeneratorHandlerFromSigner(validator Validator, signer signer.Signer) http.Handler {
return api.HTTPHandler{
Handler: &CertGeneratorHandler{
generator: &csr.Generator{Validator: validator},
signer: signer,
},
Methods: []string{"POST"},
}
}
// SetBundler allows injecting an optional Bundler into the CertGeneratorHandler.
func (cg *CertGeneratorHandler) SetBundler(caBundleFile, intBundleFile string) (err error) {
cg.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
return err
}
type genSignRequest struct {
Request *csr.CertificateRequest `json:"request"`
Profile string `json:"profile"`
Label string `json:"label"`
Bundle bool `json:"bundle"`
}
// Handle responds to requests for the CA to generate a new private
// key and certificate on behalf of the client. The format for these
// requests is documented in the API documentation.
func (cg *CertGeneratorHandler) Handle(w http.ResponseWriter, r *http.Request) error {
log.Info("request for CSR")
req := new(genSignRequest)
req.Request = csr.New()
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
return errors.NewBadRequest(err)
}
r.Body.Close()
err = json.Unmarshal(body, req)
if err != nil {
log.Warningf("failed to unmarshal request: %v", err)
return errors.NewBadRequest(err)
}
if req.Request == nil {
log.Warning("empty request received")
return errors.NewBadRequestString("missing request section")
}
if req.Request.CA != nil {
log.Warningf("request received with CA section")
return errors.NewBadRequestString("ca section only permitted in initca")
}
csr, key, err := cg.generator.ProcessRequest(req.Request)
if err != nil {
log.Warningf("failed to process CSR: %v", err)
// The validator returns a *cfssl/errors.HttpError
return err
}
signReq := signer.SignRequest{
Request: string(csr),
Profile: req.Profile,
Label: req.Label,
}
certBytes, err := cg.signer.Sign(signReq)
if err != nil {
log.Warningf("failed to sign request: %v", err)
return err
}
reqSum, err := computeSum(csr)
if err != nil {
return errors.NewBadRequest(err)
}
certSum, err := computeSum(certBytes)
if err != nil {
return errors.NewBadRequest(err)
}
result := map[string]interface{}{
"private_key": string(key),
"certificate_request": string(csr),
"certificate": string(certBytes),
"sums": map[string]Sum{
"certificate_request": reqSum,
"certificate": certSum,
},
}
if req.Bundle {
if cg.bundler == nil {
return api.SendResponseWithMessage(w, result, NoBundlerMessage,
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
}
bundle, err := cg.bundler.BundleFromPEMorDER(certBytes, nil, bundler.Optimal, "")
if err != nil {
return err
}
result["bundle"] = bundle
}
if len(req.Request.Hosts) == 0 {
return api.SendResponseWithMessage(w, result, CSRNoHostMessage,
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
}
return api.SendResponse(w, result)
}
// CSRValidate does nothing and will never return an error. It exists because NewHandler
// requires a Validator as a parameter.
func CSRValidate(req *csr.CertificateRequest) error {
return nil
}

View File

@ -1,24 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["health.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/health",
importpath = "github.com/cloudflare/cfssl/api/health",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/cloudflare/cfssl/api:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,26 +0,0 @@
package health
import (
"encoding/json"
"net/http"
"github.com/cloudflare/cfssl/api"
)
// Response contains the response to the /health API
type Response struct {
Healthy bool `json:"healthy"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) error {
response := api.NewSuccessResponse(&Response{Healthy: true})
return json.NewEncoder(w).Encode(response)
}
// NewHealthCheck creates a new handler to serve health checks.
func NewHealthCheck() http.Handler {
return api.HTTPHandler{
Handler: api.HandlerFunc(healthHandler),
Methods: []string{"GET"},
}
}

View File

@ -1,30 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["info.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/info",
importpath = "github.com/cloudflare/cfssl/api/info",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/info:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,121 +0,0 @@
// Package info implements the HTTP handler for the info command.
package info
import (
"encoding/json"
"io/ioutil"
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/info"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
)
// Handler is a type that contains the root certificates for the CA,
// and serves information on them for clients that need the certificates.
type Handler struct {
sign signer.Signer
}
// NewHandler creates a new handler to serve information on the CA's
// certificates, taking a signer to use.
func NewHandler(s signer.Signer) (http.Handler, error) {
return &api.HTTPHandler{
Handler: &Handler{
sign: s,
},
Methods: []string{"POST"},
}, nil
}
// Handle listens for incoming requests for CA information, and returns
// a list containing information on each root certificate.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
req := new(info.Req)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
return errors.NewBadRequest(err)
}
r.Body.Close()
err = json.Unmarshal(body, req)
if err != nil {
log.Warningf("failed to unmarshal request: %v", err)
return errors.NewBadRequest(err)
}
resp, err := h.sign.Info(*req)
if err != nil {
return err
}
response := api.NewSuccessResponse(resp)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
return enc.Encode(response)
}
// MultiHandler is a handler for providing the public certificates for
// a multi-root certificate authority. It takes a mapping of label to
// signer and a default label, and handles the standard information
// request as defined in the client package.
type MultiHandler struct {
signers map[string]signer.Signer
defaultLabel string
}
// NewMultiHandler constructs a MultiHandler from a mapping of labels
// to signers and the default label.
func NewMultiHandler(signers map[string]signer.Signer, defaultLabel string) (http.Handler, error) {
return &api.HTTPHandler{
Handler: &MultiHandler{
signers: signers,
defaultLabel: defaultLabel,
},
Methods: []string{"POST"},
}, nil
}
// Handle accepts client information requests, and uses the label to
// look up the signer whose public certificate should be retrieved. If
// the label is empty, the default label is used.
func (h *MultiHandler) Handle(w http.ResponseWriter, r *http.Request) error {
req := new(info.Req)
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
return errors.NewBadRequest(err)
}
r.Body.Close()
err = json.Unmarshal(body, req)
if err != nil {
log.Warningf("failed to unmarshal request: %v", err)
return errors.NewBadRequest(err)
}
log.Debug("checking label")
if req.Label == "" {
req.Label = h.defaultLabel
}
if _, ok := h.signers[req.Label]; !ok {
log.Warningf("request for invalid endpoint")
return errors.NewBadRequestString("bad label")
}
log.Debug("getting info")
resp, err := h.signers[req.Label].Info(*req)
if err != nil {
log.Infof("error getting certificate: %v", err)
return err
}
response := api.NewSuccessResponse(resp)
w.Header().Set("Content-Type", "application/json")
enc := json.NewEncoder(w)
return enc.Encode(response)
}

View File

@ -1,30 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["initca.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/initca",
importpath = "github.com/cloudflare/cfssl/api/initca",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/initca:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,61 +0,0 @@
// Package initca implements the HTTP handler for the CA initialization command
package initca
import (
"encoding/json"
"io/ioutil"
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/initca"
"github.com/cloudflare/cfssl/log"
)
// A NewCA contains a private key and certificate suitable for serving
// as the root key for a new certificate authority.
type NewCA struct {
Key string `json:"private_key"`
Cert string `json:"certificate"`
}
// initialCAHandler is an HTTP handler that accepts a JSON blob in the
// same format as the CSR endpoint; this blob should contain the
// identity information for the CA's root key. This endpoint is not
// suitable for creating intermediate certificates.
func initialCAHandler(w http.ResponseWriter, r *http.Request) error {
log.Info("setting up initial CA handler")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Warningf("failed to read request body: %v", err)
return errors.NewBadRequest(err)
}
r.Body.Close()
req := new(csr.CertificateRequest)
req.KeyRequest = csr.NewBasicKeyRequest()
err = json.Unmarshal(body, req)
if err != nil {
log.Warningf("failed to unmarshal request: %v", err)
return errors.NewBadRequest(err)
}
cert, _, key, err := initca.New(req)
if err != nil {
log.Warningf("failed to initialise new CA: %v", err)
return err
}
response := api.NewSuccessResponse(&NewCA{string(key), string(cert)})
enc := json.NewEncoder(w)
err = enc.Encode(response)
return err
}
// NewHandler returns a new http.Handler that handles request to
// initialize a CA.
func NewHandler() http.Handler {
return api.HTTPHandler{Handler: api.HandlerFunc(initialCAHandler), Methods: []string{"POST"}}
}

View File

@ -1,30 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ocspsign.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/ocsp",
importpath = "github.com/cloudflare/cfssl/api/ocsp",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,113 +0,0 @@
// Package ocsp implements the HTTP handler for the ocsp commands.
package ocsp
import (
"crypto"
"net/http"
"encoding/base64"
"encoding/json"
"io/ioutil"
"time"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
// A Handler accepts requests with a certficate parameter
// (which should be PEM-encoded) and returns a signed ocsp
// response.
type Handler struct {
signer ocsp.Signer
}
// NewHandler returns a new http.Handler that handles a ocspsign request.
func NewHandler(s ocsp.Signer) http.Handler {
return &api.HTTPHandler{
Handler: &Handler{
signer: s,
},
Methods: []string{"POST"},
}
}
// This type is meant to be unmarshalled from JSON
type jsonSignRequest struct {
Certificate string `json:"certificate"`
Status string `json:"status"`
Reason int `json:"reason,omitempty"`
RevokedAt string `json:"revoked_at,omitempty"`
IssuerHash string `json:"issuer_hash,omitempty"`
}
var nameToHash = map[string]crypto.Hash{
"MD5": crypto.MD5,
"SHA1": crypto.SHA1,
"SHA256": crypto.SHA256,
"SHA384": crypto.SHA384,
"SHA512": crypto.SHA512,
}
// Handle responds to requests for a ocsp signature. It creates and signs
// a ocsp response for the provided certificate and status. If the status
// is revoked then it also adds reason and revoked_at. The response is
// base64 encoded.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
r.Body.Close()
// Default the status to good so it matches the cli
req := &jsonSignRequest{
Status: "good",
}
err = json.Unmarshal(body, req)
if err != nil {
return errors.NewBadRequestString("Unable to parse sign request")
}
cert, err := helpers.ParseCertificatePEM([]byte(req.Certificate))
if err != nil {
log.Error("Error from ParseCertificatePEM", err)
return errors.NewBadRequestString("Malformed certificate")
}
signReq := ocsp.SignRequest{
Certificate: cert,
Status: req.Status,
}
// We need to convert the time from being a string to a time.Time
if req.Status == "revoked" {
signReq.Reason = req.Reason
// "now" is accepted and the default on the cli so default that here
if req.RevokedAt == "" || req.RevokedAt == "now" {
signReq.RevokedAt = time.Now()
} else {
signReq.RevokedAt, err = time.Parse("2006-01-02", req.RevokedAt)
if err != nil {
return errors.NewBadRequestString("Malformed revocation time")
}
}
}
if req.IssuerHash != "" {
issuerHash, ok := nameToHash[req.IssuerHash]
if !ok {
return errors.NewBadRequestString("Unsupported hash algorithm in request")
}
signReq.IssuerHash = issuerHash
}
resp, err := h.signer.Sign(signReq)
if err != nil {
return err
}
b64Resp := base64.StdEncoding.EncodeToString(resp)
result := map[string]string{"ocspResponse": b64Resp}
return api.SendResponse(w, result)
}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["revoke.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/revoke",
importpath = "github.com/cloudflare/cfssl/api/revoke",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
"//vendor/golang.org/x/crypto/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,137 +0,0 @@
// Package revoke implements the HTTP handler for the revoke command
package revoke
import (
"encoding/json"
"io/ioutil"
"net/http"
"time"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/certdb"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/ocsp"
stdocsp "golang.org/x/crypto/ocsp"
)
// A Handler accepts requests with a serial number parameter
// and revokes
type Handler struct {
dbAccessor certdb.Accessor
Signer ocsp.Signer
}
// NewHandler returns a new http.Handler that handles a revoke request.
func NewHandler(dbAccessor certdb.Accessor) http.Handler {
return &api.HTTPHandler{
Handler: &Handler{
dbAccessor: dbAccessor,
},
Methods: []string{"POST"},
}
}
// NewOCSPHandler returns a new http.Handler that handles a revoke
// request and also generates an OCSP response
func NewOCSPHandler(dbAccessor certdb.Accessor, signer ocsp.Signer) http.Handler {
return &api.HTTPHandler{
Handler: &Handler{
dbAccessor: dbAccessor,
Signer: signer,
},
Methods: []string{"POST"},
}
}
// This type is meant to be unmarshalled from JSON
type jsonRevokeRequest struct {
Serial string `json:"serial"`
AKI string `json:"authority_key_id"`
Reason string `json:"reason"`
}
// Handle responds to revocation requests. It attempts to revoke
// a certificate with a given serial number
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
r.Body.Close()
// Default the status to good so it matches the cli
var req jsonRevokeRequest
err = json.Unmarshal(body, &req)
if err != nil {
return errors.NewBadRequestString("Unable to parse revocation request")
}
if len(req.Serial) == 0 {
return errors.NewBadRequestString("serial number is required but not provided")
}
var reasonCode int
reasonCode, err = ocsp.ReasonStringToCode(req.Reason)
if err != nil {
return errors.NewBadRequestString("Invalid reason code")
}
err = h.dbAccessor.RevokeCertificate(req.Serial, req.AKI, reasonCode)
if err != nil {
return err
}
// If we were given a signer, try and generate an OCSP
// response indicating revocation
if h.Signer != nil {
// TODO: should these errors be errors?
// Grab the certificate from the database
cr, err := h.dbAccessor.GetCertificate(req.Serial, req.AKI)
if err != nil {
return err
}
if len(cr) != 1 {
return errors.NewBadRequestString("No unique certificate found")
}
cert, err := helpers.ParseCertificatePEM([]byte(cr[0].PEM))
if err != nil {
return errors.NewBadRequestString("Unable to parse certificates from PEM data")
}
sr := ocsp.SignRequest{
Certificate: cert,
Status: "revoked",
Reason: reasonCode,
RevokedAt: time.Now().UTC(),
}
ocspResponse, err := h.Signer.Sign(sr)
if err != nil {
return err
}
// We parse the OCSP response in order to get the next
// update time/expiry time
ocspParsed, err := stdocsp.ParseResponse(ocspResponse, nil)
if err != nil {
return err
}
ocspRecord := certdb.OCSPRecord{
Serial: req.Serial,
AKI: req.AKI,
Body: string(ocspResponse),
Expiry: ocspParsed.NextUpdate,
}
if err = h.dbAccessor.InsertOCSP(ocspRecord); err != nil {
return err
}
}
result := map[string]string{}
return api.SendResponse(w, result)
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["scan.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/scan",
importpath = "github.com/cloudflare/cfssl/api/scan",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/scan:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,76 +0,0 @@
package scan
import (
"encoding/json"
"net/http"
"time"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/scan"
)
// scanHandler is an HTTP handler that accepts GET parameters for host (required)
// family and scanner, and uses these to perform scans, returning a JSON blob result.
func scanHandler(w http.ResponseWriter, r *http.Request) error {
if err := r.ParseForm(); err != nil {
log.Warningf("failed to parse body: %v", err)
return errors.NewBadRequest(err)
}
family := r.Form.Get("family")
scanner := r.Form.Get("scanner")
ip := r.Form.Get("ip")
timeoutStr := r.Form.Get("timeout")
var timeout time.Duration
var err error
if timeoutStr != "" {
if timeout, err = time.ParseDuration(timeoutStr); err != nil {
return errors.NewBadRequest(err)
}
if timeout < time.Second || timeout > 5*time.Minute {
return errors.NewBadRequestString("invalid timeout given")
}
} else {
timeout = time.Minute
}
host := r.Form.Get("host")
if host == "" {
log.Warningf("no host given")
return errors.NewBadRequestString("no host given")
}
results, err := scan.Default.RunScans(host, ip, family, scanner, timeout)
if err != nil {
return errors.NewBadRequest(err)
}
return json.NewEncoder(w).Encode(api.NewSuccessResponse(results))
}
// NewHandler returns a new http.Handler that handles a scan request.
func NewHandler(caBundleFile string) (http.Handler, error) {
return api.HTTPHandler{
Handler: api.HandlerFunc(scanHandler),
Methods: []string{"GET"},
}, scan.LoadRootCAs(caBundleFile)
}
// scanInfoHandler is an HTTP handler that returns a JSON blob result describing
// the possible families and scans to be run.
func scanInfoHandler(w http.ResponseWriter, r *http.Request) error {
log.Info("setting up scaninfo handler")
response := api.NewSuccessResponse(scan.Default)
enc := json.NewEncoder(w)
return enc.Encode(response)
}
// NewInfoHandler returns a new http.Handler that handles a request for scan info.
func NewInfoHandler() http.Handler {
return api.HTTPHandler{
Handler: api.HandlerFunc(scanInfoHandler),
Methods: []string{"GET"},
}
}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["signhandler.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/api/signhandler",
importpath = "github.com/cloudflare/cfssl/api/signhandler",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api:go_default_library",
"//vendor/github.com/cloudflare/cfssl/auth:go_default_library",
"//vendor/github.com/cloudflare/cfssl/bundler:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,294 +0,0 @@
// Package signhandler provides the handlers for signers.
package signhandler
import (
"encoding/json"
"io/ioutil"
"math/big"
"net/http"
"github.com/cloudflare/cfssl/api"
"github.com/cloudflare/cfssl/auth"
"github.com/cloudflare/cfssl/bundler"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
)
// NoBundlerMessage is used to alert the user that the server does not have a bundler initialized.
const NoBundlerMessage = `This request requires a bundler, but one is not initialized for the API server.`
// A Handler accepts requests with a hostname and certficate
// parameter (which should be PEM-encoded) and returns a new signed
// certificate. It includes upstream servers indexed by their
// profile name.
type Handler struct {
signer signer.Signer
bundler *bundler.Bundler
}
// NewHandlerFromSigner generates a new Handler directly from
// an existing signer.
func NewHandlerFromSigner(signer signer.Signer) (h *api.HTTPHandler, err error) {
policy := signer.Policy()
if policy == nil {
err = errors.New(errors.PolicyError, errors.InvalidPolicy)
return
}
// Sign will only respond for profiles that have no auth provider.
// So if all of the profiles require authentication, we return an error.
haveUnauth := (policy.Default.Provider == nil)
for _, profile := range policy.Profiles {
haveUnauth = haveUnauth || (profile.Provider == nil)
}
if !haveUnauth {
err = errors.New(errors.PolicyError, errors.InvalidPolicy)
return
}
return &api.HTTPHandler{
Handler: &Handler{
signer: signer,
},
Methods: []string{"POST"},
}, nil
}
// SetBundler allows injecting an optional Bundler into the Handler.
func (h *Handler) SetBundler(caBundleFile, intBundleFile string) (err error) {
h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
return err
}
// This type is meant to be unmarshalled from JSON so that there can be a
// hostname field in the API
// TODO: Change the API such that the normal struct can be used.
type jsonSignRequest struct {
Hostname string `json:"hostname"`
Hosts []string `json:"hosts"`
Request string `json:"certificate_request"`
Subject *signer.Subject `json:"subject,omitempty"`
Profile string `json:"profile"`
Label string `json:"label"`
Serial *big.Int `json:"serial,omitempty"`
Bundle bool `json:"bundle"`
}
func jsonReqToTrue(js jsonSignRequest) signer.SignRequest {
sub := new(signer.Subject)
if js.Subject == nil {
sub = nil
} else {
// make a copy
*sub = *js.Subject
}
if js.Hostname != "" {
return signer.SignRequest{
Hosts: signer.SplitHosts(js.Hostname),
Subject: sub,
Request: js.Request,
Profile: js.Profile,
Label: js.Label,
Serial: js.Serial,
}
}
return signer.SignRequest{
Hosts: js.Hosts,
Subject: sub,
Request: js.Request,
Profile: js.Profile,
Label: js.Label,
Serial: js.Serial,
}
}
// Handle responds to requests for the CA to sign the certificate request
// present in the "certificate_request" parameter for the host named
// in the "hostname" parameter. The certificate should be PEM-encoded. If
// provided, subject information from the "subject" parameter will be used
// in place of the subject information from the CSR.
func (h *Handler) Handle(w http.ResponseWriter, r *http.Request) error {
log.Info("signature request received")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}
r.Body.Close()
var req jsonSignRequest
err = json.Unmarshal(body, &req)
if err != nil {
return errors.NewBadRequestString("Unable to parse sign request")
}
signReq := jsonReqToTrue(req)
if req.Request == "" {
return errors.NewBadRequestString("missing parameter 'certificate_request'")
}
var cert []byte
profile, err := signer.Profile(h.signer, req.Profile)
if err != nil {
return err
}
if profile.Provider != nil {
log.Error("profile requires authentication")
return errors.NewBadRequestString("authentication required")
}
cert, err = h.signer.Sign(signReq)
if err != nil {
log.Warningf("failed to sign request: %v", err)
return err
}
result := map[string]interface{}{"certificate": string(cert)}
if req.Bundle {
if h.bundler == nil {
return api.SendResponseWithMessage(w, result, NoBundlerMessage,
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
}
bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
if err != nil {
return err
}
result["bundle"] = bundle
}
log.Info("wrote response")
return api.SendResponse(w, result)
}
// An AuthHandler verifies and signs incoming signature requests.
type AuthHandler struct {
signer signer.Signer
bundler *bundler.Bundler
}
// NewAuthHandlerFromSigner creates a new AuthHandler from the signer
// that is passed in.
func NewAuthHandlerFromSigner(signer signer.Signer) (http.Handler, error) {
policy := signer.Policy()
if policy == nil {
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
}
if policy.Default == nil && policy.Profiles == nil {
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
}
// AuthSign will not respond for profiles that have no auth provider.
// So if there are no profiles with auth providers in this policy,
// we return an error.
haveAuth := (policy.Default.Provider != nil)
for _, profile := range policy.Profiles {
if haveAuth {
break
}
haveAuth = (profile.Provider != nil)
}
if !haveAuth {
return nil, errors.New(errors.PolicyError, errors.InvalidPolicy)
}
return &api.HTTPHandler{
Handler: &AuthHandler{
signer: signer,
},
Methods: []string{"POST"},
}, nil
}
// SetBundler allows injecting an optional Bundler into the Handler.
func (h *AuthHandler) SetBundler(caBundleFile, intBundleFile string) (err error) {
h.bundler, err = bundler.NewBundler(caBundleFile, intBundleFile)
return err
}
// Handle receives the incoming request, validates it, and processes it.
func (h *AuthHandler) Handle(w http.ResponseWriter, r *http.Request) error {
log.Info("signature request received")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Errorf("failed to read response body: %v", err)
return err
}
r.Body.Close()
var aReq auth.AuthenticatedRequest
err = json.Unmarshal(body, &aReq)
if err != nil {
log.Errorf("failed to unmarshal authenticated request: %v", err)
return errors.NewBadRequest(err)
}
var req jsonSignRequest
err = json.Unmarshal(aReq.Request, &req)
if err != nil {
log.Errorf("failed to unmarshal request from authenticated request: %v", err)
return errors.NewBadRequestString("Unable to parse authenticated sign request")
}
// Sanity checks to ensure that we have a valid policy. This
// should have been checked in NewAuthHandler.
policy := h.signer.Policy()
if policy == nil {
log.Critical("signer was initialised without a signing policy")
return errors.NewBadRequestString("invalid policy")
}
profile, err := signer.Profile(h.signer, req.Profile)
if err != nil {
return err
}
if profile.Provider == nil {
log.Error("profile has no authentication provider")
return errors.NewBadRequestString("no authentication provider")
}
if !profile.Provider.Verify(&aReq) {
log.Warning("received authenticated request with invalid token")
return errors.NewBadRequestString("invalid token")
}
signReq := jsonReqToTrue(req)
if signReq.Request == "" {
return errors.NewBadRequestString("missing parameter 'certificate_request'")
}
cert, err := h.signer.Sign(signReq)
if err != nil {
log.Errorf("signature failed: %v", err)
return err
}
result := map[string]interface{}{"certificate": string(cert)}
if req.Bundle {
if h.bundler == nil {
return api.SendResponseWithMessage(w, result, NoBundlerMessage,
errors.New(errors.PolicyError, errors.InvalidRequest).ErrorCode)
}
bundle, err := h.bundler.BundleFromPEMorDER(cert, nil, bundler.Optimal, "")
if err != nil {
return err
}
result["bundle"] = bundle
}
log.Info("wrote response")
return api.SendResponse(w, result)
}

View File

@ -1,33 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"bundle.go",
"bundler.go",
"doc.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/bundler",
importpath = "github.com/cloudflare/cfssl/bundler",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ubiquity:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,186 +0,0 @@
package bundler
import (
"bytes"
"crypto/ecdsa"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"time"
"github.com/cloudflare/cfssl/helpers"
)
// A Bundle contains a certificate and its trust chain. It is intended
// to store the most widely applicable chain, with shortness an
// explicit goal.
type Bundle struct {
Chain []*x509.Certificate
Cert *x509.Certificate
Root *x509.Certificate
Key interface{}
Issuer *pkix.Name
Subject *pkix.Name
Expires time.Time
LeafExpires time.Time
Hostnames []string
Status *BundleStatus
}
// BundleStatus is designated for various status reporting.
type BundleStatus struct {
// A flag on whether a new bundle is generated
IsRebundled bool `json:"rebundled"`
// A list of SKIs of expiring certificates
ExpiringSKIs []string `json:"expiring_SKIs"`
// A list of untrusted root store names
Untrusted []string `json:"untrusted_root_stores"`
// A list of human readable warning messages based on the bundle status.
Messages []string `json:"messages"`
// A status code consists of binary flags
Code int `json:"code"`
}
type chain []*x509.Certificate
func (c chain) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
for _, cert := range c {
buf.Write(pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw}))
}
ret := bytes.TrimSpace(buf.Bytes())
return json.Marshal(string(ret))
}
// PemBlockToString turns a pem.Block into the string encoded form.
func PemBlockToString(block *pem.Block) string {
if block.Bytes == nil || block.Type == "" {
return ""
}
return string(bytes.TrimSpace(pem.EncodeToMemory(block)))
}
var typeToName = map[int]string{
3: "CommonName",
5: "SerialNumber",
6: "Country",
7: "Locality",
8: "Province",
9: "StreetAddress",
10: "Organization",
11: "OrganizationalUnit",
17: "PostalCode",
}
type names []pkix.AttributeTypeAndValue
func (n names) MarshalJSON() ([]byte, error) {
var buf bytes.Buffer
for _, name := range n {
buf.WriteString(fmt.Sprintf("/%s=%s", typeToName[name.Type[3]], name.Value))
}
return json.Marshal(buf.String())
}
// MarshalJSON serialises the bundle to JSON. The resulting JSON
// structure contains the bundle (as a sequence of PEM-encoded
// certificates), the certificate, the private key, the size of they
// key, the issuer(s), the subject name(s), the expiration, the
// hostname(s), the OCSP server, and the signature on the certificate.
func (b *Bundle) MarshalJSON() ([]byte, error) {
if b == nil || b.Cert == nil {
return nil, errors.New("no certificate in bundle")
}
var keyBytes, rootBytes []byte
var keyLength int
var keyType, keyString string
keyLength = helpers.KeyLength(b.Cert.PublicKey)
switch b.Cert.PublicKeyAlgorithm {
case x509.ECDSA:
keyType = fmt.Sprintf("%d-bit ECDSA", keyLength)
case x509.RSA:
keyType = fmt.Sprintf("%d-bit RSA", keyLength)
case x509.DSA:
keyType = "DSA"
default:
keyType = "Unknown"
}
switch key := b.Key.(type) {
case *rsa.PrivateKey:
keyBytes = x509.MarshalPKCS1PrivateKey(key)
keyString = PemBlockToString(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: keyBytes})
case *ecdsa.PrivateKey:
keyBytes, _ = x509.MarshalECPrivateKey(key)
keyString = PemBlockToString(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyBytes})
case fmt.Stringer:
keyString = key.String()
}
if len(b.Hostnames) == 0 {
b.buildHostnames()
}
var ocspSupport = false
if b.Cert.OCSPServer != nil {
ocspSupport = true
}
var crlSupport = false
if b.Cert.CRLDistributionPoints != nil {
crlSupport = true
}
if b.Root != nil {
rootBytes = b.Root.Raw
}
return json.Marshal(map[string]interface{}{
"bundle": chain(b.Chain),
"root": PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: rootBytes}),
"crt": PemBlockToString(&pem.Block{Type: "CERTIFICATE", Bytes: b.Cert.Raw}),
"key": keyString,
"key_type": keyType,
"key_size": keyLength,
"issuer": names(b.Issuer.Names),
"subject": names(b.Subject.Names),
"expires": b.Expires,
"leaf_expires": b.LeafExpires,
"hostnames": b.Hostnames,
"ocsp_support": ocspSupport,
"crl_support": crlSupport,
"ocsp": b.Cert.OCSPServer,
"signature": helpers.SignatureString(b.Cert.SignatureAlgorithm),
"status": b.Status,
})
}
// buildHostnames sets bundle.Hostnames by the x509 cert's subject CN and DNS names
// Since the subject CN may overlap with one of the DNS names, it needs to handle
// the duplication by a set.
func (b *Bundle) buildHostnames() {
if b.Cert == nil {
return
}
// hset keeps a set of unique hostnames.
hset := make(map[string]bool)
// insert CN into hset
if b.Cert.Subject.CommonName != "" {
hset[b.Cert.Subject.CommonName] = true
}
// insert all DNS names into hset
for _, h := range b.Cert.DNSNames {
hset[h] = true
}
// convert hset to an array of hostnames
b.Hostnames = make([]string, len(hset))
i := 0
for h := range hset {
b.Hostnames[i] = h
i++
}
}

View File

@ -1,843 +0,0 @@
// Package bundler implements certificate bundling functionality for
// CFSSL.
package bundler
import (
"bytes"
"crypto"
"crypto/ecdsa"
"crypto/rsa"
"crypto/tls"
"crypto/x509"
"encoding/pem"
goerr "errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ubiquity"
)
// IntermediateStash contains the path to the directory where
// downloaded intermediates should be saved.
// When unspecified, downloaded intermediates are not saved.
var IntermediateStash string
// BundleFlavor is named optimization strategy on certificate chain selection when bundling.
type BundleFlavor string
const (
// Optimal means the shortest chain with newest intermediates and
// the most advanced crypto.
Optimal BundleFlavor = "optimal"
// Ubiquitous is aimed to provide the chain which is accepted
// by the most platforms.
Ubiquitous BundleFlavor = "ubiquitous"
// Force means the bundler only verfiies the input as a valid bundle, not optimization is done.
Force BundleFlavor = "force"
)
const (
sha2Warning = "The bundle contains certificates signed with advanced hash functions such as SHA2, which are problematic for certain operating systems, e.g. Windows XP SP2."
ecdsaWarning = "The bundle contains ECDSA signatures, which are problematic for certain operating systems, e.g. Windows XP, Android 2.2 and Android 2.3."
expiringWarningStub = "The bundle is expiring within 30 days."
untrustedWarningStub = "The bundle may not be trusted by the following platform(s):"
ubiquityWarning = "Unable to measure bundle ubiquity: No platform metadata present."
)
// A Bundler contains the certificate pools for producing certificate
// bundles. It contains any intermediates and root certificates that
// should be used.
type Bundler struct {
RootPool *x509.CertPool
IntermediatePool *x509.CertPool
KnownIssuers map[string]bool
opts options
}
type options struct {
keyUsages []x509.ExtKeyUsage
}
var defaultOptions = options{
keyUsages: []x509.ExtKeyUsage{
x509.ExtKeyUsageAny,
},
}
// An Option sets options such as allowed key usages, etc.
type Option func(*options)
// WithKeyUsages lets you set which Extended Key Usage values are acceptable. By
// default x509.ExtKeyUsageAny will be used.
func WithKeyUsages(usages ...x509.ExtKeyUsage) Option {
return func(o *options) {
o.keyUsages = usages
}
}
// NewBundler creates a new Bundler from the files passed in; these
// files should contain a list of valid root certificates and a list
// of valid intermediate certificates, respectively.
func NewBundler(caBundleFile, intBundleFile string, opt ...Option) (*Bundler, error) {
var caBundle, intBundle []byte
var err error
if caBundleFile != "" {
log.Debug("Loading CA bundle: ", caBundleFile)
caBundle, err = ioutil.ReadFile(caBundleFile)
if err != nil {
log.Errorf("root bundle failed to load: %v", err)
return nil, errors.Wrap(errors.RootError, errors.ReadFailed, err)
}
}
if intBundleFile != "" {
log.Debug("Loading Intermediate bundle: ", intBundleFile)
intBundle, err = ioutil.ReadFile(intBundleFile)
if err != nil {
log.Errorf("intermediate bundle failed to load: %v", err)
return nil, errors.Wrap(errors.IntermediatesError, errors.ReadFailed, err)
}
}
if IntermediateStash != "" {
if _, err = os.Stat(IntermediateStash); err != nil && os.IsNotExist(err) {
log.Infof("intermediate stash directory %s doesn't exist, creating", IntermediateStash)
err = os.MkdirAll(IntermediateStash, 0755)
if err != nil {
log.Errorf("failed to create intermediate stash directory %s: %v",
IntermediateStash, err)
return nil, err
}
log.Infof("intermediate stash directory %s created", IntermediateStash)
}
}
return NewBundlerFromPEM(caBundle, intBundle, opt...)
}
// NewBundlerFromPEM creates a new Bundler from PEM-encoded root certificates and
// intermediate certificates.
// If caBundlePEM is nil, the resulting Bundler can only do "Force" bundle.
func NewBundlerFromPEM(caBundlePEM, intBundlePEM []byte, opt ...Option) (*Bundler, error) {
opts := defaultOptions
for _, o := range opt {
o(&opts)
}
log.Debug("parsing root certificates from PEM")
roots, err := helpers.ParseCertificatesPEM(caBundlePEM)
if err != nil {
log.Errorf("failed to parse root bundle: %v", err)
return nil, errors.New(errors.RootError, errors.ParseFailed)
}
log.Debug("parse intermediate certificates from PEM")
intermediates, err := helpers.ParseCertificatesPEM(intBundlePEM)
if err != nil {
log.Errorf("failed to parse intermediate bundle: %v", err)
return nil, errors.New(errors.IntermediatesError, errors.ParseFailed)
}
b := &Bundler{
KnownIssuers: map[string]bool{},
IntermediatePool: x509.NewCertPool(),
opts: opts,
}
log.Debug("building certificate pools")
// RootPool will be nil if caBundlePEM is nil, also
// that translates to caBundleFile is "".
// Systems root store will be used.
if caBundlePEM != nil {
b.RootPool = x509.NewCertPool()
}
for _, c := range roots {
b.RootPool.AddCert(c)
b.KnownIssuers[string(c.Signature)] = true
}
for _, c := range intermediates {
b.IntermediatePool.AddCert(c)
b.KnownIssuers[string(c.Signature)] = true
}
log.Debug("bundler set up")
return b, nil
}
// VerifyOptions generates an x509 VerifyOptions structure that can be
// used for verifying certificates.
func (b *Bundler) VerifyOptions() x509.VerifyOptions {
return x509.VerifyOptions{
Roots: b.RootPool,
Intermediates: b.IntermediatePool,
KeyUsages: b.opts.keyUsages,
}
}
// BundleFromFile takes a set of files containing the PEM-encoded leaf certificate
// (optionally along with some intermediate certs), the PEM-encoded private key
// and returns the bundle built from that key and the certificate(s).
func (b *Bundler) BundleFromFile(bundleFile, keyFile string, flavor BundleFlavor, password string) (*Bundle, error) {
log.Debug("Loading Certificate: ", bundleFile)
certsRaw, err := ioutil.ReadFile(bundleFile)
if err != nil {
return nil, errors.Wrap(errors.CertificateError, errors.ReadFailed, err)
}
var keyPEM []byte
// Load private key PEM only if a file is given
if keyFile != "" {
log.Debug("Loading private key: ", keyFile)
keyPEM, err = ioutil.ReadFile(keyFile)
if err != nil {
log.Debugf("failed to read private key: ", err)
return nil, errors.Wrap(errors.PrivateKeyError, errors.ReadFailed, err)
}
if len(keyPEM) == 0 {
log.Debug("key is empty")
return nil, errors.Wrap(errors.PrivateKeyError, errors.DecodeFailed, err)
}
}
return b.BundleFromPEMorDER(certsRaw, keyPEM, flavor, password)
}
// BundleFromPEMorDER builds a certificate bundle from the set of byte
// slices containing the PEM or DER-encoded certificate(s), private key.
func (b *Bundler) BundleFromPEMorDER(certsRaw, keyPEM []byte, flavor BundleFlavor, password string) (*Bundle, error) {
log.Debug("bundling from PEM files")
var key crypto.Signer
var err error
if len(keyPEM) != 0 {
key, err = helpers.ParsePrivateKeyPEM(keyPEM)
if err != nil {
log.Debugf("failed to parse private key: %v", err)
return nil, err
}
}
certs, err := helpers.ParseCertificatesPEM(certsRaw)
if err != nil {
// If PEM doesn't work try DER
var keyDER crypto.Signer
var errDER error
certs, keyDER, errDER = helpers.ParseCertificatesDER(certsRaw, password)
// Only use DER key if no key read from file
if key == nil && keyDER != nil {
key = keyDER
}
if errDER != nil {
log.Debugf("failed to parse certificates: %v", err)
// If neither parser works pass along PEM error
return nil, err
}
}
if len(certs) == 0 {
log.Debugf("no certificates found")
return nil, errors.New(errors.CertificateError, errors.DecodeFailed)
}
log.Debugf("bundle ready")
return b.Bundle(certs, key, flavor)
}
// BundleFromRemote fetches the certificate served by the server at
// serverName (or ip, if the ip argument is not the empty string). It
// is expected that the method will be able to make a connection at
// port 443. The certificate used by the server in this connection is
// used to build the bundle, which will necessarily be keyless.
func (b *Bundler) BundleFromRemote(serverName, ip string, flavor BundleFlavor) (*Bundle, error) {
config := &tls.Config{
RootCAs: b.RootPool,
ServerName: serverName,
}
// Dial by IP if present
var dialName string
if ip != "" {
dialName = ip + ":443"
} else {
dialName = serverName + ":443"
}
log.Debugf("bundling from remote %s", dialName)
dialer := &net.Dialer{Timeout: time.Duration(5) * time.Second}
conn, err := tls.DialWithDialer(dialer, "tcp", dialName, config)
var dialError string
// If there's an error in tls.Dial, try again with
// InsecureSkipVerify to fetch the remote bundle to (re-)bundle
// with. If the bundle is indeed not usable (expired, mismatched
// hostnames, etc.), report the error. Otherwise, create a
// working bundle and insert the tls error in the bundle.Status.
if err != nil {
log.Debugf("dial failed: %v", err)
// record the error msg
dialError = fmt.Sprintf("Failed rigid TLS handshake with %s: %v", dialName, err)
// dial again with InsecureSkipVerify
log.Debugf("try again with InsecureSkipVerify.")
config.InsecureSkipVerify = true
conn, err = tls.DialWithDialer(dialer, "tcp", dialName, config)
if err != nil {
log.Debugf("dial with InsecureSkipVerify failed: %v", err)
return nil, errors.Wrap(errors.DialError, errors.Unknown, err)
}
}
connState := conn.ConnectionState()
certs := connState.PeerCertificates
err = conn.VerifyHostname(serverName)
if err != nil {
log.Debugf("failed to verify hostname: %v", err)
return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
// Bundle with remote certs. Inject the initial dial error, if any, to the status reporting.
bundle, err := b.Bundle(certs, nil, flavor)
if err != nil {
return nil, err
} else if dialError != "" {
bundle.Status.Messages = append(bundle.Status.Messages, dialError)
}
return bundle, err
}
type fetchedIntermediate struct {
Cert *x509.Certificate
Name string
}
// fetchRemoteCertificate retrieves a single URL pointing to a certificate
// and attempts to first parse it as a DER-encoded certificate; if
// this fails, it attempts to decode it as a PEM-encoded certificate.
func fetchRemoteCertificate(certURL string) (fi *fetchedIntermediate, err error) {
log.Debugf("fetching remote certificate: %s", certURL)
var resp *http.Response
resp, err = http.Get(certURL)
if err != nil {
log.Debugf("failed HTTP get: %v", err)
return
}
defer resp.Body.Close()
var certData []byte
certData, err = ioutil.ReadAll(resp.Body)
if err != nil {
log.Debugf("failed to read response body: %v", err)
return
}
log.Debugf("attempting to parse certificate as DER")
crt, err := x509.ParseCertificate(certData)
if err != nil {
log.Debugf("attempting to parse certificate as PEM")
crt, err = helpers.ParseCertificatePEM(certData)
if err != nil {
log.Debugf("failed to parse certificate: %v", err)
return
}
}
log.Debugf("certificate fetch succeeds")
fi = &fetchedIntermediate{Cert: crt, Name: constructCertFileName(crt)}
return
}
func reverse(certs []*x509.Certificate) []*x509.Certificate {
n := len(certs)
if n == 0 {
return certs
}
rcerts := []*x509.Certificate{}
for i := n - 1; i >= 0; i-- {
rcerts = append(rcerts, certs[i])
}
return rcerts
}
// Check if the certs form a partial cert chain: every cert verifies
// the signature of the one in front of it.
func partialVerify(certs []*x509.Certificate) bool {
n := len(certs)
if n == 0 {
return false
}
for i := 0; i < n-1; i++ {
if certs[i].CheckSignatureFrom(certs[i+1]) != nil {
return false
}
}
return true
}
func isSelfSigned(cert *x509.Certificate) bool {
return cert.CheckSignatureFrom(cert) == nil
}
func isChainRootNode(cert *x509.Certificate) bool {
if isSelfSigned(cert) {
return true
}
return false
}
func (b *Bundler) verifyChain(chain []*fetchedIntermediate) bool {
// This process will verify if the root of the (partial) chain is in our root pool,
// and will fail otherwise.
log.Debugf("verifying chain")
for vchain := chain[:]; len(vchain) > 0; vchain = vchain[1:] {
cert := vchain[0]
// If this is a certificate in one of the pools, skip it.
if b.KnownIssuers[string(cert.Cert.Signature)] {
log.Debugf("certificate is known")
continue
}
_, err := cert.Cert.Verify(b.VerifyOptions())
if err != nil {
log.Debugf("certificate failed verification: %v", err)
return false
} else if len(chain) == len(vchain) && isChainRootNode(cert.Cert) {
// The first certificate in the chain is a root; it shouldn't be stored.
log.Debug("looking at root certificate, will not store")
continue
}
// leaf cert has an empty name, don't store leaf cert.
if cert.Name == "" {
continue
}
log.Debug("add certificate to intermediate pool:", cert.Name)
b.IntermediatePool.AddCert(cert.Cert)
b.KnownIssuers[string(cert.Cert.Signature)] = true
if IntermediateStash != "" {
fileName := filepath.Join(IntermediateStash, cert.Name)
var block = pem.Block{Type: "CERTIFICATE", Bytes: cert.Cert.Raw}
log.Debugf("write intermediate to stash directory: %s", fileName)
// If the write fails, verification should not fail.
err = ioutil.WriteFile(fileName, pem.EncodeToMemory(&block), 0644)
if err != nil {
log.Errorf("failed to write new intermediate: %v", err)
} else {
log.Info("stashed new intermediate ", cert.Name)
}
}
}
return true
}
// constructCertFileName returns a uniquely identifying file name for a certificate
func constructCertFileName(cert *x509.Certificate) string {
// construct the filename as the CN with no period and space
name := strings.Replace(cert.Subject.CommonName, ".", "", -1)
name = strings.Replace(name, " ", "", -1)
// add SKI and serial number as extra identifier
name += fmt.Sprintf("_%x", cert.SubjectKeyId)
name += fmt.Sprintf("_%x", cert.SerialNumber.Bytes())
name += ".crt"
return name
}
// fetchIntermediates goes through each of the URLs in the AIA "Issuing
// CA" extensions and fetches those certificates. If those
// certificates are not present in either the root pool or
// intermediate pool, the certificate is saved to file and added to
// the list of intermediates to be used for verification. This will
// not add any new certificates to the root pool; if the ultimate
// issuer is not trusted, fetching the certicate here will not change
// that.
func (b *Bundler) fetchIntermediates(certs []*x509.Certificate) (err error) {
if IntermediateStash != "" {
log.Debugf("searching intermediates")
if _, err := os.Stat(IntermediateStash); err != nil && os.IsNotExist(err) {
log.Infof("intermediate stash directory %s doesn't exist, creating", IntermediateStash)
err = os.MkdirAll(IntermediateStash, 0755)
if err != nil {
log.Errorf("failed to create intermediate stash directory %s: %v", IntermediateStash, err)
return err
}
log.Infof("intermediate stash directory %s created", IntermediateStash)
}
}
// stores URLs and certificate signatures that have been seen
seen := map[string]bool{}
var foundChains int
// Construct a verify chain as a reversed partial bundle,
// such that the certs are ordered by promxity to the root CAs.
var chain []*fetchedIntermediate
for i, cert := range certs {
var name string
// Only construct filenames for non-leaf intermediate certs
// so they will be saved to disk if necessary.
// Leaf cert gets a empty name and will be skipped.
if i > 0 {
name = constructCertFileName(cert)
}
chain = append([]*fetchedIntermediate{{cert, name}}, chain...)
seen[string(cert.Signature)] = true
}
// Verify the chain and store valid intermediates in the chain.
// If it doesn't verify, fetch the intermediates and extend the chain
// in a DFS manner and verify each time we hit a root.
for {
if len(chain) == 0 {
log.Debugf("search complete")
if foundChains == 0 {
return x509.UnknownAuthorityError{}
}
return nil
}
current := chain[0]
var advanced bool
if b.verifyChain(chain) {
foundChains++
}
log.Debugf("walk AIA issuers")
for _, url := range current.Cert.IssuingCertificateURL {
if seen[url] {
log.Debugf("url %s has been seen", url)
continue
}
crt, err := fetchRemoteCertificate(url)
if err != nil {
continue
} else if seen[string(crt.Cert.Signature)] {
log.Debugf("fetched certificate is known")
continue
}
seen[url] = true
seen[string(crt.Cert.Signature)] = true
chain = append([]*fetchedIntermediate{crt}, chain...)
advanced = true
break
}
if !advanced {
log.Debugf("didn't advance, stepping back")
chain = chain[1:]
}
}
}
// Bundle takes an X509 certificate (already in the
// Certificate structure), a private key as crypto.Signer in one of the appropriate
// formats (i.e. *rsa.PrivateKey or *ecdsa.PrivateKey, or even a opaque key), using them to
// build a certificate bundle.
func (b *Bundler) Bundle(certs []*x509.Certificate, key crypto.Signer, flavor BundleFlavor) (*Bundle, error) {
log.Infof("bundling certificate for %+v", certs[0].Subject)
if len(certs) == 0 {
return nil, nil
}
// Detect reverse ordering of the cert chain.
if len(certs) > 1 && !partialVerify(certs) {
rcerts := reverse(certs)
if partialVerify(rcerts) {
certs = rcerts
}
}
var ok bool
cert := certs[0]
if key != nil {
switch {
case cert.PublicKeyAlgorithm == x509.RSA:
var rsaPublicKey *rsa.PublicKey
if rsaPublicKey, ok = key.Public().(*rsa.PublicKey); !ok {
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
}
if cert.PublicKey.(*rsa.PublicKey).N.Cmp(rsaPublicKey.N) != 0 {
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
}
case cert.PublicKeyAlgorithm == x509.ECDSA:
var ecdsaPublicKey *ecdsa.PublicKey
if ecdsaPublicKey, ok = key.Public().(*ecdsa.PublicKey); !ok {
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
}
if cert.PublicKey.(*ecdsa.PublicKey).X.Cmp(ecdsaPublicKey.X) != 0 {
return nil, errors.New(errors.PrivateKeyError, errors.KeyMismatch)
}
default:
return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECC)
}
} else {
switch {
case cert.PublicKeyAlgorithm == x509.RSA:
case cert.PublicKeyAlgorithm == x509.ECDSA:
default:
return nil, errors.New(errors.PrivateKeyError, errors.NotRSAOrECC)
}
}
bundle := new(Bundle)
bundle.Cert = cert
bundle.Key = key
bundle.Issuer = &cert.Issuer
bundle.Subject = &cert.Subject
bundle.buildHostnames()
if flavor == Force {
// force bundle checks the certificates
// forms a verification chain.
if !partialVerify(certs) {
return nil,
errors.Wrap(errors.CertificateError, errors.VerifyFailed,
goerr.New("Unable to verify the certificate chain"))
}
bundle.Chain = certs
} else {
// disallow self-signed cert
if cert.CheckSignatureFrom(cert) == nil {
return nil, errors.New(errors.CertificateError, errors.SelfSigned)
}
chains, err := cert.Verify(b.VerifyOptions())
if err != nil {
log.Debugf("verification failed: %v", err)
// If the error was an unknown authority, try to fetch
// the intermediate specified in the AIA and add it to
// the intermediates bundle.
if _, ok := err.(x509.UnknownAuthorityError); !ok {
return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
log.Debugf("searching for intermediates via AIA issuer")
searchErr := b.fetchIntermediates(certs)
if searchErr != nil {
log.Debugf("search failed: %v", searchErr)
return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
log.Debugf("verifying new chain")
chains, err = cert.Verify(b.VerifyOptions())
if err != nil {
log.Debugf("failed to verify chain: %v", err)
return nil, errors.Wrap(errors.CertificateError, errors.VerifyFailed, err)
}
log.Debugf("verify ok")
}
var matchingChains [][]*x509.Certificate
switch flavor {
case Optimal:
matchingChains = optimalChains(chains)
case Ubiquitous:
if len(ubiquity.Platforms) == 0 {
log.Warning("No metadata, Ubiquitous falls back to Optimal.")
}
matchingChains = ubiquitousChains(chains)
default:
matchingChains = ubiquitousChains(chains)
}
bundle.Chain = matchingChains[0]
}
statusCode := int(errors.Success)
var messages []string
// Check if bundle is expiring.
expiringCerts := checkExpiringCerts(bundle.Chain)
if len(expiringCerts) > 0 {
statusCode |= errors.BundleExpiringBit
messages = append(messages, expirationWarning(expiringCerts))
}
// Check if bundle contains SHA2 certs.
if ubiquity.ChainHashUbiquity(bundle.Chain) <= ubiquity.SHA2Ubiquity {
statusCode |= errors.BundleNotUbiquitousBit
messages = append(messages, sha2Warning)
}
// Check if bundle contains ECDSA signatures.
if ubiquity.ChainKeyAlgoUbiquity(bundle.Chain) <= ubiquity.ECDSA256Ubiquity {
statusCode |= errors.BundleNotUbiquitousBit
messages = append(messages, ecdsaWarning)
}
// when forcing a bundle, bundle ubiquity doesn't matter
// also we don't retrieve the anchoring root of the bundle
var untrusted []string
if flavor != Force {
// Add root store presence info
root := bundle.Chain[len(bundle.Chain)-1]
bundle.Root = root
log.Infof("the anchoring root is %v", root.Subject)
// Check if there is any platform that doesn't trust the chain.
// Also, an warning will be generated if ubiquity.Platforms is nil,
untrusted = ubiquity.UntrustedPlatforms(root)
untrustedMsg := untrustedPlatformsWarning(untrusted)
if len(untrustedMsg) > 0 {
log.Debug("Populate untrusted platform warning.")
statusCode |= errors.BundleNotUbiquitousBit
messages = append(messages, untrustedMsg)
}
}
// Check if there is any platform that rejects the chain because of SHA1 deprecation.
sha1Msgs := ubiquity.SHA1DeprecationMessages(bundle.Chain)
if len(sha1Msgs) > 0 {
log.Debug("Populate SHA1 deprecation warning.")
statusCode |= errors.BundleNotUbiquitousBit
messages = append(messages, sha1Msgs...)
}
bundle.Status = &BundleStatus{ExpiringSKIs: getSKIs(bundle.Chain, expiringCerts), Code: statusCode, Messages: messages, Untrusted: untrusted}
// attempt to not to include the root certificate for optimization
if flavor != Force {
// Include at least one intermediate if the leaf has enabled OCSP and is not CA.
if bundle.Cert.OCSPServer != nil && !bundle.Cert.IsCA && len(bundle.Chain) <= 2 {
// No op. Return one intermediate if there is one.
} else {
// do not include the root.
bundle.Chain = bundle.Chain[:len(bundle.Chain)-1]
}
}
bundle.Status.IsRebundled = diff(bundle.Chain, certs)
bundle.Expires = helpers.ExpiryTime(bundle.Chain)
bundle.LeafExpires = bundle.Chain[0].NotAfter
log.Debugf("bundle complete")
return bundle, nil
}
// checkExpiringCerts returns indices of certs that are expiring within 30 days.
func checkExpiringCerts(chain []*x509.Certificate) (expiringIntermediates []int) {
now := time.Now()
for i, cert := range chain {
if cert.NotAfter.Sub(now).Hours() < 720 {
expiringIntermediates = append(expiringIntermediates, i)
}
}
return
}
// getSKIs returns a list of cert subject key id in the bundle chain with matched indices.
func getSKIs(chain []*x509.Certificate, indices []int) (skis []string) {
for _, index := range indices {
ski := fmt.Sprintf("%X", chain[index].SubjectKeyId)
skis = append(skis, ski)
}
return
}
// expirationWarning generates a warning message with expiring certs.
func expirationWarning(expiringIntermediates []int) (ret string) {
if len(expiringIntermediates) == 0 {
return
}
ret = expiringWarningStub
if len(expiringIntermediates) > 1 {
ret = ret + "The expiring certs are"
} else {
ret = ret + "The expiring cert is"
}
for _, index := range expiringIntermediates {
ret = ret + " #" + strconv.Itoa(index+1)
}
ret = ret + " in the chain."
return
}
// untrustedPlatformsWarning generates a warning message with untrusted platform names.
func untrustedPlatformsWarning(platforms []string) string {
if len(ubiquity.Platforms) == 0 {
return ubiquityWarning
}
if len(platforms) == 0 {
return ""
}
msg := untrustedWarningStub
for i, platform := range platforms {
if i > 0 {
msg += ","
}
msg += " " + platform
}
msg += "."
return msg
}
// Optimal chains are the shortest chains, with newest intermediates and most advanced crypto suite being the tie breaker.
func optimalChains(chains [][]*x509.Certificate) [][]*x509.Certificate {
// Find shortest chains
chains = ubiquity.Filter(chains, ubiquity.CompareChainLength)
// Find the chains with longest expiry.
chains = ubiquity.Filter(chains, ubiquity.CompareChainExpiry)
// Find the chains with more advanced crypto suite
chains = ubiquity.Filter(chains, ubiquity.CompareChainCryptoSuite)
return chains
}
// Ubiquitous chains are the chains with highest platform coverage and break ties with the optimal strategy.
func ubiquitousChains(chains [][]*x509.Certificate) [][]*x509.Certificate {
// Filter out chains with highest cross platform ubiquity.
chains = ubiquity.Filter(chains, ubiquity.ComparePlatformUbiquity)
// Prefer that all intermediates are SHA-2 certs if the leaf is a SHA-2 cert, in order to improve ubiquity.
chains = ubiquity.Filter(chains, ubiquity.CompareSHA2Homogeneity)
// Filter shortest chains
chains = ubiquity.Filter(chains, ubiquity.CompareChainLength)
// Filter chains with highest signature hash ubiquity.
chains = ubiquity.Filter(chains, ubiquity.CompareChainHashUbiquity)
// Filter chains with highest keyAlgo ubiquity.
chains = ubiquity.Filter(chains, ubiquity.CompareChainKeyAlgoUbiquity)
// Filter chains with intermediates that last longer.
chains = ubiquity.Filter(chains, ubiquity.CompareExpiryUbiquity)
// Use the optimal strategy as final tie breaker.
return optimalChains(chains)
}
// diff checkes if two input cert chains are not identical
func diff(chain1, chain2 []*x509.Certificate) bool {
// Check if bundled one is different from the input.
diff := false
if len(chain1) != len(chain2) {
diff = true
} else {
for i := 0; i < len(chain1); i++ {
cert1 := chain1[i]
cert2 := chain2[i]
// Use signature to differentiate.
if !bytes.Equal(cert1.Signature, cert2.Signature) {
diff = true
break
}
}
}
return diff
}

View File

@ -1,16 +0,0 @@
// Package bundler provides an API for creating certificate bundles,
// which contain a trust chain of certificates. Generally, the bundles
// will also include the private key (but this is not strictly
// required). In this package, a bundle refers to a certificate with
// full trust chain -- all certificates in the chain in one file or
// buffer.
//
// The first step in creating a certificate bundle is to create a
// Bundler. A Bundler must be created from a pre-existing certificate
// authority bundle and an intermediate certificate bundle. Once the
// Bundler is initialised, bundles may be created using a variety of
// methods: from PEM- or DER-encoded files, directly from the relevant
// Go structures, or by starting with the certificate from a remote
// system. These functions return a Bundle value, which may be
// serialised to JSON.
package bundler

View File

@ -17,11 +17,7 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/cloudflare/cfssl/certdb/dbconf:all-srcs",
"//vendor/github.com/cloudflare/cfssl/certdb/sql:all-srcs",
],
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["db_config.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/certdb/dbconf",
importpath = "github.com/cloudflare/cfssl/certdb/dbconf",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/jmoiron/sqlx:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,57 +0,0 @@
package dbconf
import (
"encoding/json"
"errors"
"io/ioutil"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/log"
"github.com/jmoiron/sqlx"
)
// DBConfig contains the database driver name and configuration to be passed to Open
type DBConfig struct {
DriverName string `json:"driver"`
DataSourceName string `json:"data_source"`
}
// LoadFile attempts to load the db configuration file stored at the path
// and returns the configuration. On error, it returns nil.
func LoadFile(path string) (cfg *DBConfig, err error) {
log.Debugf("loading db configuration file from %s", path)
if path == "" {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid path"))
}
var body []byte
body, err = ioutil.ReadFile(path)
if err != nil {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("could not read configuration file"))
}
cfg = &DBConfig{}
err = json.Unmarshal(body, &cfg)
if err != nil {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy,
errors.New("failed to unmarshal configuration: "+err.Error()))
}
if cfg.DataSourceName == "" || cfg.DriverName == "" {
return nil, cferr.Wrap(cferr.PolicyError, cferr.InvalidPolicy, errors.New("invalid db configuration"))
}
return
}
// DBFromConfig opens a sql.DB from settings in a db config file
func DBFromConfig(path string) (db *sqlx.DB, err error) {
var dbCfg *DBConfig
dbCfg, err = LoadFile(path)
if err != nil {
return nil, err
}
return sqlx.Open(dbCfg.DriverName, dbCfg.DataSourceName)
}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["database_accessor.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/certdb/sql",
importpath = "github.com/cloudflare/cfssl/certdb/sql",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certdb:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/jmoiron/sqlx:go_default_library",
"//vendor/github.com/kisielk/sqlstruct:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,352 +0,0 @@
package sql
import (
"errors"
"fmt"
"time"
"github.com/cloudflare/cfssl/certdb"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/jmoiron/sqlx"
"github.com/kisielk/sqlstruct"
)
// Match to sqlx
func init() {
sqlstruct.TagName = "db"
}
const (
insertSQL = `
INSERT INTO certificates (serial_number, authority_key_identifier, ca_label, status, reason, expiry, revoked_at, pem)
VALUES (:serial_number, :authority_key_identifier, :ca_label, :status, :reason, :expiry, :revoked_at, :pem);`
selectSQL = `
SELECT %s FROM certificates
WHERE (serial_number = ? AND authority_key_identifier = ?);`
selectAllUnexpiredSQL = `
SELECT %s FROM certificates
WHERE CURRENT_TIMESTAMP < expiry;`
selectAllRevokedAndUnexpiredWithLabelSQL = `
SELECT %s FROM certificates
WHERE CURRENT_TIMESTAMP < expiry AND status='revoked' AND ca_label= ?;`
selectAllRevokedAndUnexpiredSQL = `
SELECT %s FROM certificates
WHERE CURRENT_TIMESTAMP < expiry AND status='revoked';`
updateRevokeSQL = `
UPDATE certificates
SET status='revoked', revoked_at=CURRENT_TIMESTAMP, reason=:reason
WHERE (serial_number = :serial_number AND authority_key_identifier = :authority_key_identifier);`
insertOCSPSQL = `
INSERT INTO ocsp_responses (serial_number, authority_key_identifier, body, expiry)
VALUES (:serial_number, :authority_key_identifier, :body, :expiry);`
updateOCSPSQL = `
UPDATE ocsp_responses
SET body = :body, expiry = :expiry
WHERE (serial_number = :serial_number AND authority_key_identifier = :authority_key_identifier);`
selectAllUnexpiredOCSPSQL = `
SELECT %s FROM ocsp_responses
WHERE CURRENT_TIMESTAMP < expiry;`
selectOCSPSQL = `
SELECT %s FROM ocsp_responses
WHERE (serial_number = ? AND authority_key_identifier = ?);`
)
// Accessor implements certdb.Accessor interface.
type Accessor struct {
db *sqlx.DB
}
func wrapSQLError(err error) error {
if err != nil {
return cferr.Wrap(cferr.CertStoreError, cferr.Unknown, err)
}
return nil
}
func (d *Accessor) checkDB() error {
if d.db == nil {
return cferr.Wrap(cferr.CertStoreError, cferr.Unknown,
errors.New("unknown db object, please check SetDB method"))
}
return nil
}
// NewAccessor returns a new Accessor.
func NewAccessor(db *sqlx.DB) *Accessor {
return &Accessor{db: db}
}
// SetDB changes the underlying sql.DB object Accessor is manipulating.
func (d *Accessor) SetDB(db *sqlx.DB) {
d.db = db
return
}
// InsertCertificate puts a certdb.CertificateRecord into db.
func (d *Accessor) InsertCertificate(cr certdb.CertificateRecord) error {
err := d.checkDB()
if err != nil {
return err
}
res, err := d.db.NamedExec(insertSQL, &certdb.CertificateRecord{
Serial: cr.Serial,
AKI: cr.AKI,
CALabel: cr.CALabel,
Status: cr.Status,
Reason: cr.Reason,
Expiry: cr.Expiry.UTC(),
RevokedAt: cr.RevokedAt.UTC(),
PEM: cr.PEM,
})
if err != nil {
return wrapSQLError(err)
}
numRowsAffected, err := res.RowsAffected()
if numRowsAffected == 0 {
return cferr.Wrap(cferr.CertStoreError, cferr.InsertionFailed, fmt.Errorf("failed to insert the certificate record"))
}
if numRowsAffected != 1 {
return wrapSQLError(fmt.Errorf("%d rows are affected, should be 1 row", numRowsAffected))
}
return err
}
// GetCertificate gets a certdb.CertificateRecord indexed by serial.
func (d *Accessor) GetCertificate(serial, aki string) (crs []certdb.CertificateRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectSQL), sqlstruct.Columns(certdb.CertificateRecord{})), serial, aki)
if err != nil {
return nil, wrapSQLError(err)
}
return crs, nil
}
// GetUnexpiredCertificates gets all unexpired certificate from db.
func (d *Accessor) GetUnexpiredCertificates() (crs []certdb.CertificateRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectAllUnexpiredSQL), sqlstruct.Columns(certdb.CertificateRecord{})))
if err != nil {
return nil, wrapSQLError(err)
}
return crs, nil
}
// GetRevokedAndUnexpiredCertificates gets all revoked and unexpired certificate from db (for CRLs).
func (d *Accessor) GetRevokedAndUnexpiredCertificates() (crs []certdb.CertificateRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectAllRevokedAndUnexpiredSQL), sqlstruct.Columns(certdb.CertificateRecord{})))
if err != nil {
return nil, wrapSQLError(err)
}
return crs, nil
}
// GetRevokedAndUnexpiredCertificatesByLabel gets all revoked and unexpired certificate from db (for CRLs) with specified ca_label.
func (d *Accessor) GetRevokedAndUnexpiredCertificatesByLabel(label string) (crs []certdb.CertificateRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&crs, fmt.Sprintf(d.db.Rebind(selectAllRevokedAndUnexpiredWithLabelSQL), sqlstruct.Columns(certdb.CertificateRecord{})), label)
if err != nil {
return nil, wrapSQLError(err)
}
return crs, nil
}
// RevokeCertificate updates a certificate with a given serial number and marks it revoked.
func (d *Accessor) RevokeCertificate(serial, aki string, reasonCode int) error {
err := d.checkDB()
if err != nil {
return err
}
result, err := d.db.NamedExec(updateRevokeSQL, &certdb.CertificateRecord{
AKI: aki,
Reason: reasonCode,
Serial: serial,
})
if err != nil {
return wrapSQLError(err)
}
numRowsAffected, err := result.RowsAffected()
if numRowsAffected == 0 {
return cferr.Wrap(cferr.CertStoreError, cferr.RecordNotFound, fmt.Errorf("failed to revoke the certificate: certificate not found"))
}
if numRowsAffected != 1 {
return wrapSQLError(fmt.Errorf("%d rows are affected, should be 1 row", numRowsAffected))
}
return err
}
// InsertOCSP puts a new certdb.OCSPRecord into the db.
func (d *Accessor) InsertOCSP(rr certdb.OCSPRecord) error {
err := d.checkDB()
if err != nil {
return err
}
result, err := d.db.NamedExec(insertOCSPSQL, &certdb.OCSPRecord{
AKI: rr.AKI,
Body: rr.Body,
Expiry: rr.Expiry.UTC(),
Serial: rr.Serial,
})
if err != nil {
return wrapSQLError(err)
}
numRowsAffected, err := result.RowsAffected()
if numRowsAffected == 0 {
return cferr.Wrap(cferr.CertStoreError, cferr.InsertionFailed, fmt.Errorf("failed to insert the OCSP record"))
}
if numRowsAffected != 1 {
return wrapSQLError(fmt.Errorf("%d rows are affected, should be 1 row", numRowsAffected))
}
return err
}
// GetOCSP retrieves a certdb.OCSPRecord from db by serial.
func (d *Accessor) GetOCSP(serial, aki string) (ors []certdb.OCSPRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&ors, fmt.Sprintf(d.db.Rebind(selectOCSPSQL), sqlstruct.Columns(certdb.OCSPRecord{})), serial, aki)
if err != nil {
return nil, wrapSQLError(err)
}
return ors, nil
}
// GetUnexpiredOCSPs retrieves all unexpired certdb.OCSPRecord from db.
func (d *Accessor) GetUnexpiredOCSPs() (ors []certdb.OCSPRecord, err error) {
err = d.checkDB()
if err != nil {
return nil, err
}
err = d.db.Select(&ors, fmt.Sprintf(d.db.Rebind(selectAllUnexpiredOCSPSQL), sqlstruct.Columns(certdb.OCSPRecord{})))
if err != nil {
return nil, wrapSQLError(err)
}
return ors, nil
}
// UpdateOCSP updates a ocsp response record with a given serial number.
func (d *Accessor) UpdateOCSP(serial, aki, body string, expiry time.Time) error {
err := d.checkDB()
if err != nil {
return err
}
result, err := d.db.NamedExec(updateOCSPSQL, &certdb.OCSPRecord{
AKI: aki,
Body: body,
Expiry: expiry.UTC(),
Serial: serial,
})
if err != nil {
return wrapSQLError(err)
}
numRowsAffected, err := result.RowsAffected()
if numRowsAffected == 0 {
return cferr.Wrap(cferr.CertStoreError, cferr.RecordNotFound, fmt.Errorf("failed to update the OCSP record"))
}
if numRowsAffected != 1 {
return wrapSQLError(fmt.Errorf("%d rows are affected, should be 1 row", numRowsAffected))
}
return err
}
// UpsertOCSP update a ocsp response record with a given serial number,
// or insert the record if it doesn't yet exist in the db
// Implementation note:
// We didn't implement 'upsert' with SQL statement and we lost race condition
// prevention provided by underlying DBMS.
// Reasoning:
// 1. it's diffcult to support multiple DBMS backends in the same time, the
// SQL syntax differs from one to another.
// 2. we don't need a strict simultaneous consistency between OCSP and certificate
// status. It's OK that a OCSP response still shows 'good' while the
// corresponding certificate is being revoked seconds ago, as long as the OCSP
// response catches up to be eventually consistent (within hours to days).
// Write race condition between OCSP writers on OCSP table is not a problem,
// since we don't have write race condition on Certificate table and OCSP
// writers should periodically use Certificate table to update OCSP table
// to catch up.
func (d *Accessor) UpsertOCSP(serial, aki, body string, expiry time.Time) error {
err := d.checkDB()
if err != nil {
return err
}
result, err := d.db.NamedExec(updateOCSPSQL, &certdb.OCSPRecord{
AKI: aki,
Body: body,
Expiry: expiry.UTC(),
Serial: serial,
})
if err != nil {
return wrapSQLError(err)
}
numRowsAffected, err := result.RowsAffected()
if numRowsAffected == 0 {
return d.InsertOCSP(certdb.OCSPRecord{Serial: serial, AKI: aki, Body: body, Expiry: expiry})
}
if numRowsAffected != 1 {
return wrapSQLError(fmt.Errorf("%d rows are affected, should be 1 row", numRowsAffected))
}
return err
}

View File

@ -1,24 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["certinfo.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/certinfo",
importpath = "github.com/cloudflare/cfssl/certinfo",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/cloudflare/cfssl/helpers:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,166 +0,0 @@
package certinfo
import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"errors"
"fmt"
"io/ioutil"
"net"
"strings"
"time"
"github.com/cloudflare/cfssl/helpers"
)
// Certificate represents a JSON description of an X.509 certificate.
type Certificate struct {
Subject Name `json:"subject,omitempty"`
Issuer Name `json:"issuer,omitempty"`
SerialNumber string `json:"serial_number,omitempty"`
SANs []string `json:"sans,omitempty"`
NotBefore time.Time `json:"not_before"`
NotAfter time.Time `json:"not_after"`
SignatureAlgorithm string `json:"sigalg"`
AKI string `json:"authority_key_id"`
SKI string `json:"subject_key_id"`
RawPEM string `json:"pem"`
}
// Name represents a JSON description of a PKIX Name
type Name struct {
CommonName string `json:"common_name,omitempty"`
SerialNumber string `json:"serial_number,omitempty"`
Country string `json:"country,omitempty"`
Organization string `json:"organization,omitempty"`
OrganizationalUnit string `json:"organizational_unit,omitempty"`
Locality string `json:"locality,omitempty"`
Province string `json:"province,omitempty"`
StreetAddress string `json:"street_address,omitempty"`
PostalCode string `json:"postal_code,omitempty"`
Names []interface{} `json:"names,omitempty"`
//ExtraNames []interface{} `json:"extra_names,omitempty"`
}
// ParseName parses a new name from a *pkix.Name
func ParseName(name pkix.Name) Name {
n := Name{
CommonName: name.CommonName,
SerialNumber: name.SerialNumber,
Country: strings.Join(name.Country, ","),
Organization: strings.Join(name.Organization, ","),
OrganizationalUnit: strings.Join(name.OrganizationalUnit, ","),
Locality: strings.Join(name.Locality, ","),
Province: strings.Join(name.Province, ","),
StreetAddress: strings.Join(name.StreetAddress, ","),
PostalCode: strings.Join(name.PostalCode, ","),
}
for i := range name.Names {
n.Names = append(n.Names, name.Names[i].Value)
}
// ExtraNames aren't supported in Go 1.4
// for i := range name.ExtraNames {
// n.ExtraNames = append(n.ExtraNames, name.ExtraNames[i].Value)
// }
return n
}
func formatKeyID(id []byte) string {
var s string
for i, c := range id {
if i > 0 {
s += ":"
}
s += fmt.Sprintf("%02X", c)
}
return s
}
// ParseCertificate parses an x509 certificate.
func ParseCertificate(cert *x509.Certificate) *Certificate {
c := &Certificate{
RawPEM: string(helpers.EncodeCertificatePEM(cert)),
SignatureAlgorithm: helpers.SignatureString(cert.SignatureAlgorithm),
NotBefore: cert.NotBefore,
NotAfter: cert.NotAfter,
Subject: ParseName(cert.Subject),
Issuer: ParseName(cert.Issuer),
SANs: cert.DNSNames,
AKI: formatKeyID(cert.AuthorityKeyId),
SKI: formatKeyID(cert.SubjectKeyId),
SerialNumber: cert.SerialNumber.String(),
}
for _, ip := range cert.IPAddresses {
c.SANs = append(c.SANs, ip.String())
}
return c
}
// ParseCertificateFile parses x509 certificate file.
func ParseCertificateFile(certFile string) (*Certificate, error) {
certPEM, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, err
}
return ParseCertificatePEM(certPEM)
}
// ParseCertificatePEM parses an x509 certificate PEM.
func ParseCertificatePEM(certPEM []byte) (*Certificate, error) {
cert, err := helpers.ParseCertificatePEM(certPEM)
if err != nil {
return nil, err
}
return ParseCertificate(cert), nil
}
// ParseCSRPEM uses the helper to parse an x509 CSR PEM.
func ParseCSRPEM(csrPEM []byte) (*x509.CertificateRequest, error) {
csrObject, err := helpers.ParseCSRPEM(csrPEM)
if err != nil {
return nil, err
}
return csrObject, nil
}
// ParseCSRFile uses the helper to parse an x509 CSR PEM file.
func ParseCSRFile(csrFile string) (*x509.CertificateRequest, error) {
csrPEM, err := ioutil.ReadFile(csrFile)
if err != nil {
return nil, err
}
return ParseCSRPEM(csrPEM)
}
// ParseCertificateDomain parses the certificate served by the given domain.
func ParseCertificateDomain(domain string) (cert *Certificate, err error) {
var host, port string
if host, port, err = net.SplitHostPort(domain); err != nil {
host = domain
port = "443"
}
var conn *tls.Conn
conn, err = tls.DialWithDialer(&net.Dialer{Timeout: 10 * time.Second}, "tcp", net.JoinHostPort(host, port), &tls.Config{InsecureSkipVerify: true})
if err != nil {
return
}
defer conn.Close()
if len(conn.ConnectionState().PeerCertificates) == 0 {
return nil, errors.New("received no server certificates")
}
cert = ParseCertificate(conn.ConnectionState().PeerCertificates[0])
return
}

View File

@ -1,53 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"cli.go",
"config.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli",
importpath = "github.com/cloudflare/cfssl/cli",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/config:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer/universal:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/bundle:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/certinfo:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/crl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/gencert:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/gencrl:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/gencsr:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/genkey:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/info:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/ocspdump:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/ocsprefresh:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/ocspserve:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/ocspsign:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/printdefault:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/revoke:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/scan:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/selfsign:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/serve:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/sign:all-srcs",
"//vendor/github.com/cloudflare/cfssl/cli/version:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["bundle.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/bundle",
importpath = "github.com/cloudflare/cfssl/cli/bundle",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/bundler:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ubiquity:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,88 +0,0 @@
// Package bundle implements the bundle command.
package bundle
import (
"errors"
"fmt"
"github.com/cloudflare/cfssl/bundler"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/ubiquity"
)
// Usage text of 'cfssl bundle'
var bundlerUsageText = `cfssl bundle -- create a certificate bundle that contains the client cert
Usage of bundle:
- Bundle local certificate files
cfssl bundle -cert file [-ca-bundle file] [-int-bundle file] [-int-dir dir] [-metadata file] [-key keyfile] [-flavor optimal|ubiquitous|force] [-password password]
- Bundle certificate from remote server.
cfssl bundle -domain domain_name [-ip ip_address] [-ca-bundle file] [-int-bundle file] [-int-dir dir] [-metadata file]
Flags:
`
// flags used by 'cfssl bundle'
var bundlerFlags = []string{"cert", "key", "ca-bundle", "int-bundle", "flavor", "int-dir", "metadata", "domain", "ip", "password"}
// bundlerMain is the main CLI of bundler functionality.
func bundlerMain(args []string, c cli.Config) (err error) {
bundler.IntermediateStash = c.IntDir
ubiquity.LoadPlatforms(c.Metadata)
flavor := bundler.BundleFlavor(c.Flavor)
var b *bundler.Bundler
// If it is a force bundle, don't require ca bundle and intermediate bundle
// Otherwise, initialize a bundler with CA bundle and intermediate bundle.
if flavor == bundler.Force {
b = &bundler.Bundler{}
} else {
b, err = bundler.NewBundler(c.CABundleFile, c.IntBundleFile)
if err != nil {
return
}
}
var bundle *bundler.Bundle
if c.CertFile != "" {
if c.CertFile == "-" {
var certPEM, keyPEM []byte
certPEM, err = cli.ReadStdin(c.CertFile)
if err != nil {
return
}
if c.KeyFile != "" {
keyPEM, err = cli.ReadStdin(c.KeyFile)
if err != nil {
return
}
}
bundle, err = b.BundleFromPEMorDER(certPEM, keyPEM, flavor, "")
if err != nil {
return
}
} else {
// Bundle the client cert
bundle, err = b.BundleFromFile(c.CertFile, c.KeyFile, flavor, c.Password)
if err != nil {
return
}
}
} else if c.Domain != "" {
bundle, err = b.BundleFromRemote(c.Domain, c.IP, flavor)
if err != nil {
return
}
} else {
return errors.New("Must specify bundle target through -cert or -domain")
}
marshaled, err := bundle.MarshalJSON()
if err != nil {
return
}
fmt.Printf("%s", marshaled)
return
}
// Command assembles the definition of Command 'bundle'
var Command = &cli.Command{UsageText: bundlerUsageText, Flags: bundlerFlags, Main: bundlerMain}

View File

@ -1,27 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["certinfo.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/certinfo",
importpath = "github.com/cloudflare/cfssl/cli/certinfo",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certinfo:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,89 +0,0 @@
// Package certinfo implements the certinfo command
package certinfo
import (
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"github.com/cloudflare/cfssl/certinfo"
"github.com/cloudflare/cfssl/cli"
)
// Usage text of 'cfssl certinfo'
var dataUsageText = `cfssl certinfo -- output certinfo about the given cert
Usage of certinfo:
- Data from local certificate files
cfssl certinfo -cert file
- Data from local CSR file
cfssl certinfo -csr file
- Data from certificate from remote server.
cfssl certinfo -domain domain_name
Flags:
`
// flags used by 'cfssl certinfo'
var certinfoFlags = []string{"cert", "csr", "domain"}
// certinfoMain is the main CLI of certinfo functionality
func certinfoMain(args []string, c cli.Config) (err error) {
var cert *certinfo.Certificate
var csr *x509.CertificateRequest
if c.CertFile != "" {
if c.CertFile == "-" {
var certPEM []byte
if certPEM, err = cli.ReadStdin(c.CertFile); err != nil {
return
}
if cert, err = certinfo.ParseCertificatePEM(certPEM); err != nil {
return
}
} else {
if cert, err = certinfo.ParseCertificateFile(c.CertFile); err != nil {
return
}
}
} else if c.CSRFile != "" {
if c.CSRFile == "-" {
var csrPEM []byte
if csrPEM, err = cli.ReadStdin(c.CSRFile); err != nil {
return
}
if csr, err = certinfo.ParseCSRPEM(csrPEM); err != nil {
return
}
} else {
if csr, err = certinfo.ParseCSRFile(c.CSRFile); err != nil {
return
}
}
} else if c.Domain != "" {
if cert, err = certinfo.ParseCertificateDomain(c.Domain); err != nil {
return
}
} else {
return errors.New("Must specify certinfo target through -cert, -csr, or -domain")
}
var b []byte
if cert != nil {
b, err = json.MarshalIndent(cert, "", " ")
} else if csr != nil {
b, err = json.MarshalIndent(csr, "", " ")
}
if err != nil {
return
}
fmt.Println(string(b))
return
}
// Command assembles the definition of Command 'certinfo'
var Command = &cli.Command{UsageText: dataUsageText, Flags: certinfoFlags, Main: certinfoMain}

View File

@ -1,199 +0,0 @@
// Package cli provides the template for adding new cfssl commands
package cli
/*
cfssl is the command line tool to issue/sign/bundle client certificate. It's
also a tool to start a HTTP server to handle web requests for signing, bundling
and verification.
Usage:
cfssl command [-flags] arguments
The commands are defined in the cli subpackages and include
bundle create a certificate bundle
sign signs a certificate signing request (CSR)
serve starts a HTTP server handling sign and bundle requests
version prints the current cfssl version
genkey generates a key and an associated CSR
gencert generates a key and a signed certificate
gencsr generates a certificate request
selfsign generates a self-signed certificate
ocspsign signs an OCSP response
Use "cfssl [command] -help" to find out more about a command.
*/
import (
"encoding/base64"
"encoding/json"
"errors"
"flag"
"fmt"
"io/ioutil"
"os"
"github.com/cloudflare/cfssl/config"
)
// Command holds the implementation details of a cfssl command.
type Command struct {
// The Usage Text
UsageText string
// Flags to look up in the global table
Flags []string
// Main runs the command, args are the arguments after flags
Main func(args []string, c Config) error
}
var cmdName string
// usage is the cfssl usage heading. It will be appended with names of defined commands in cmds
// to form the final usage message of cfssl.
const usage = `Usage:
Available commands:
`
// printDefaultValue is a helper function to print out a user friendly
// usage message of a flag. It's useful since we want to write customized
// usage message on selected subsets of the global flag set. It is
// borrowed from standard library source code. Since flag value type is
// not exported, default string flag values are printed without
// quotes. The only exception is the empty string, which is printed as "".
func printDefaultValue(f *flag.Flag) {
format := " -%s=%s: %s\n"
if f.DefValue == "" {
format = " -%s=%q: %s\n"
}
fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage)
}
// PopFirstArgument returns the first element and the rest of a string
// slice and return error if failed to do so. It is a helper function
// to parse non-flag arguments previously used in cfssl commands.
func PopFirstArgument(args []string) (string, []string, error) {
if len(args) < 1 {
return "", nil, errors.New("not enough arguments are supplied --- please refer to the usage")
}
return args[0], args[1:], nil
}
// Start is the entrance point of cfssl command line tools.
func Start(cmds map[string]*Command) error {
// cfsslFlagSet is the flag sets for cfssl.
var cfsslFlagSet = flag.NewFlagSet("cfssl", flag.ExitOnError)
var c Config
registerFlags(&c, cfsslFlagSet)
// Initial parse of command line arguments. By convention, only -h/-help is supported.
if flag.Usage == nil {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, usage)
for name := range cmds {
fmt.Fprintf(os.Stderr, "\t%s\n", name)
}
fmt.Fprintf(os.Stderr, "Top-level flags:\n")
flag.PrintDefaults()
}
}
flag.Parse()
if flag.NArg() < 1 {
fmt.Fprintf(os.Stderr, "No command is given.\n")
flag.Usage()
return errors.New("no command was given")
}
// Clip out the command name and args for the command
cmdName = flag.Arg(0)
args := flag.Args()[1:]
cmd, found := cmds[cmdName]
if !found {
fmt.Fprintf(os.Stderr, "Command %s is not defined.\n", cmdName)
flag.Usage()
return errors.New("undefined command")
}
// always have flag 'loglevel' for each command
cmd.Flags = append(cmd.Flags, "loglevel")
// The usage of each individual command is re-written to mention
// flags defined and referenced only in that command.
cfsslFlagSet.Usage = func() {
fmt.Fprintf(os.Stderr, "\t%s", cmd.UsageText)
for _, name := range cmd.Flags {
if f := cfsslFlagSet.Lookup(name); f != nil {
printDefaultValue(f)
}
}
}
// Parse all flags and take the rest as argument lists for the command
cfsslFlagSet.Parse(args)
args = cfsslFlagSet.Args()
var err error
if c.ConfigFile != "" {
c.CFG, err = config.LoadFile(c.ConfigFile)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to load config file: %v", err)
return errors.New("failed to load config file")
}
}
if err := cmd.Main(args, c); err != nil {
fmt.Fprintln(os.Stderr, err)
return err
}
return nil
}
// ReadStdin reads from stdin if the file is "-"
func ReadStdin(filename string) ([]byte, error) {
if filename == "-" {
return ioutil.ReadAll(os.Stdin)
}
return ioutil.ReadFile(filename)
}
// PrintCert outputs a cert, key and csr to stdout
func PrintCert(key, csrBytes, cert []byte) {
out := map[string]string{}
if cert != nil {
out["cert"] = string(cert)
}
if key != nil {
out["key"] = string(key)
}
if csrBytes != nil {
out["csr"] = string(csrBytes)
}
jsonOut, err := json.Marshal(out)
if err != nil {
return
}
fmt.Printf("%s\n", jsonOut)
}
// PrintOCSPResponse outputs an OCSP response to stdout
// ocspResponse is base64 encoded
func PrintOCSPResponse(resp []byte) {
b64Resp := base64.StdEncoding.EncodeToString(resp)
out := map[string]string{"ocspResponse": b64Resp}
jsonOut, err := json.Marshal(out)
if err != nil {
return
}
fmt.Printf("%s\n", jsonOut)
}
// PrintCRL outputs the CRL to stdout
func PrintCRL(certList []byte) {
b64Resp := base64.StdEncoding.EncodeToString(certList)
fmt.Printf("%s\n", b64Resp)
}

View File

@ -1,147 +0,0 @@
package cli
import (
"flag"
"time"
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer/universal"
)
// Config is a type to hold flag values used by cfssl commands.
type Config struct {
Hostname string
CertFile string
CSRFile string
CAFile string
CAKeyFile string
TLSCertFile string
TLSKeyFile string
MutualTLSCAFile string
MutualTLSCNRegex string
TLSRemoteCAs string
MutualTLSCertFile string
MutualTLSKeyFile string
KeyFile string
IntermediatesFile string
CABundleFile string
IntBundleFile string
Address string
Port int
MinTLSVersion string
Password string
ConfigFile string
CFG *config.Config
Profile string
IsCA bool
RenewCA bool
IntDir string
Flavor string
Metadata string
Domain string
IP string
Remote string
Label string
AuthKey string
ResponderFile string
ResponderKeyFile string
Status string
Reason string
RevokedAt string
Interval time.Duration
List bool
Family string
Timeout time.Duration
Scanner string
CSVFile string
NumWorkers int
MaxHosts int
Responses string
Path string
CRL string
Usage string
PGPPrivate string
PGPName string
Serial string
CNOverride string
AKI string
DBConfigFile string
CRLExpiration time.Duration
Disable string
}
// registerFlags defines all cfssl command flags and associates their values with variables.
func registerFlags(c *Config, f *flag.FlagSet) {
f.StringVar(&c.Hostname, "hostname", "", "Hostname for the cert, could be a comma-separated hostname list")
f.StringVar(&c.CertFile, "cert", "", "Client certificate that contains the public key")
f.StringVar(&c.CSRFile, "csr", "", "Certificate signature request file for new public key")
f.StringVar(&c.CAFile, "ca", "", "CA used to sign the new certificate -- accepts '[file:]fname' or 'env:varname'")
f.StringVar(&c.CAKeyFile, "ca-key", "", "CA private key -- accepts '[file:]fname' or 'env:varname'")
f.StringVar(&c.TLSCertFile, "tls-cert", "", "Other endpoint CA to set up TLS protocol")
f.StringVar(&c.TLSKeyFile, "tls-key", "", "Other endpoint CA private key")
f.StringVar(&c.MutualTLSCAFile, "mutual-tls-ca", "", "Mutual TLS - require clients be signed by this CA ")
f.StringVar(&c.MutualTLSCNRegex, "mutual-tls-cn", "", "Mutual TLS - regex for whitelist of allowed client CNs")
f.StringVar(&c.TLSRemoteCAs, "tls-remote-ca", "", "CAs to trust for remote TLS requests")
f.StringVar(&c.MutualTLSCertFile, "mutual-tls-client-cert", "", "Mutual TLS - client certificate to call remote instance requiring client certs")
f.StringVar(&c.MutualTLSKeyFile, "mutual-tls-client-key", "", "Mutual TLS - client key to call remote instance requiring client certs")
f.StringVar(&c.KeyFile, "key", "", "private key for the certificate")
f.StringVar(&c.IntermediatesFile, "intermediates", "", "intermediate certs")
f.StringVar(&c.CABundleFile, "ca-bundle", "", "path to root certificate store")
f.StringVar(&c.IntBundleFile, "int-bundle", "", "path to intermediate certificate store")
f.StringVar(&c.Address, "address", "127.0.0.1", "Address to bind")
f.IntVar(&c.Port, "port", 8888, "Port to bind")
f.StringVar(&c.MinTLSVersion, "min-tls-version", "", "Minimum version of TLS to use, defaults to 1.0")
f.StringVar(&c.ConfigFile, "config", "", "path to configuration file")
f.StringVar(&c.Profile, "profile", "", "signing profile to use")
f.BoolVar(&c.IsCA, "initca", false, "initialise new CA")
f.BoolVar(&c.RenewCA, "renewca", false, "re-generate a CA certificate from existing CA certificate/key")
f.StringVar(&c.IntDir, "int-dir", "", "specify intermediates directory")
f.StringVar(&c.Flavor, "flavor", "ubiquitous", "Bundle Flavor: ubiquitous, optimal and force.")
f.StringVar(&c.Metadata, "metadata", "", "Metadata file for root certificate presence. The content of the file is a json dictionary (k,v): each key k is SHA-1 digest of a root certificate while value v is a list of key store filenames.")
f.StringVar(&c.Domain, "domain", "", "remote server domain name")
f.StringVar(&c.IP, "ip", "", "remote server ip")
f.StringVar(&c.Remote, "remote", "", "remote CFSSL server")
f.StringVar(&c.Label, "label", "", "key label to use in remote CFSSL server")
f.StringVar(&c.AuthKey, "authkey", "", "key to authenticate requests to remote CFSSL server")
f.StringVar(&c.ResponderFile, "responder", "", "Certificate for OCSP responder")
f.StringVar(&c.ResponderKeyFile, "responder-key", "", "private key for OCSP responder certificate")
f.StringVar(&c.Status, "status", "good", "Status of the certificate: good, revoked, unknown")
f.StringVar(&c.Reason, "reason", "0", "Reason code for revocation")
f.StringVar(&c.RevokedAt, "revoked-at", "now", "Date of revocation (YYYY-MM-DD)")
f.DurationVar(&c.Interval, "interval", 4*helpers.OneDay, "Interval between OCSP updates (default: 96h)")
f.BoolVar(&c.List, "list", false, "list possible scanners")
f.StringVar(&c.Family, "family", "", "scanner family regular expression")
f.StringVar(&c.Scanner, "scanner", "", "scanner regular expression")
f.DurationVar(&c.Timeout, "timeout", 5*time.Minute, "duration (ns, us, ms, s, m, h) to scan each host before timing out")
f.StringVar(&c.CSVFile, "csv", "", "file containing CSV of hosts")
f.IntVar(&c.NumWorkers, "num-workers", 10, "number of workers to use for scan")
f.IntVar(&c.MaxHosts, "max-hosts", 100, "maximum number of hosts to scan")
f.StringVar(&c.Responses, "responses", "", "file to load OCSP responses from")
f.StringVar(&c.Path, "path", "/", "Path on which the server will listen")
f.StringVar(&c.CRL, "crl", "", "CRL URL Override")
f.StringVar(&c.Password, "password", "0", "Password for accessing PKCS #12 data passed to bundler")
f.StringVar(&c.Usage, "usage", "", "usage of private key")
f.StringVar(&c.PGPPrivate, "pgp-private", "", "file to load a PGP Private key decryption")
f.StringVar(&c.PGPName, "pgp-name", "", "PGP public key name, can be a comma-sepearted key name list")
f.StringVar(&c.Serial, "serial", "", "certificate serial number")
f.StringVar(&c.CNOverride, "cn", "", "certificate common name (CN)")
f.StringVar(&c.AKI, "aki", "", "certificate issuer (authority) key identifier")
f.StringVar(&c.DBConfigFile, "db-config", "", "certificate db configuration file")
f.DurationVar(&c.CRLExpiration, "expiry", 7*helpers.OneDay, "time from now after which the CRL will expire (default: one week)")
f.IntVar(&log.Level, "loglevel", log.LevelInfo, "Log level (0 = DEBUG, 5 = FATAL)")
f.StringVar(&c.Disable, "disable", "", "endpoints to disable")
}
// RootFromConfig returns a universal signer Root structure that can
// be used to produce a signer.
func RootFromConfig(c *Config) universal.Root {
return universal.Root{
Config: map[string]string{
"cert-file": c.CAFile,
"key-file": c.CAKeyFile,
},
ForceRemote: c.Remote != "",
}
}

View File

@ -1,33 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["crl.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/crl",
importpath = "github.com/cloudflare/cfssl/cli/crl",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certdb/dbconf:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb/sql:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/crl:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/jmoiron/sqlx:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,105 +0,0 @@
//Package crl implements the crl command
package crl
import (
"os"
"github.com/cloudflare/cfssl/certdb/dbconf"
certsql "github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/crl"
cferr "github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/jmoiron/sqlx"
)
var crlUsageText = `cfssl crl -- generate a new Certificate Revocation List from Database
Usage of crl:
cfssl crl
Flags:
`
var crlFlags = []string{"db-config", "ca", "ca-key", "expiry"}
func generateCRL(c cli.Config) (crlBytes []byte, err error) {
if c.CAFile == "" {
log.Error("need CA certificate (provide one with -ca)")
return
}
if c.CAKeyFile == "" {
log.Error("need CA key (provide one with -ca-key)")
return
}
var db *sqlx.DB
if c.DBConfigFile != "" {
db, err = dbconf.DBFromConfig(c.DBConfigFile)
if err != nil {
return nil, err
}
} else {
log.Error("no Database specified!")
return nil, err
}
dbAccessor := certsql.NewAccessor(db)
log.Debug("loading CA: ", c.CAFile)
ca, err := helpers.ReadBytes(c.CAFile)
if err != nil {
return nil, err
}
log.Debug("loading CA key: ", c.CAKeyFile)
cakey, err := helpers.ReadBytes(c.CAKeyFile)
if err != nil {
return nil, cferr.Wrap(cferr.CertificateError, cferr.ReadFailed, err)
}
// Parse the PEM encoded certificate
issuerCert, err := helpers.ParseCertificatePEM(ca)
if err != nil {
return nil, err
}
strPassword := os.Getenv("CFSSL_CA_PK_PASSWORD")
password := []byte(strPassword)
if strPassword == "" {
password = nil
}
// Parse the key given
key, err := helpers.ParsePrivateKeyPEMWithPassword(cakey, password)
if err != nil {
log.Debug("malformed private key %v", err)
return nil, err
}
certs, err := dbAccessor.GetRevokedAndUnexpiredCertificates()
if err != nil {
return nil, err
}
req, err := crl.NewCRLFromDB(certs, issuerCert, key, c.CRLExpiration)
if err != nil {
return nil, err
}
return req, nil
}
func crlMain(args []string, c cli.Config) (err error) {
req, err := generateCRL(c)
if err != nil {
return err
}
cli.PrintCRL(req)
return
}
// Command assembles the definition of Command 'crl'
var Command = &cli.Command{UsageText: crlUsageText, Flags: crlFlags, Main: crlMain}

View File

@ -1,33 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gencert.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/gencert",
importpath = "github.com/cloudflare/cfssl/cli/gencert",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api/generator:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli/genkey:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli/sign:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/initca:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,165 +0,0 @@
// Package gencert implements the gencert command.
package gencert
import (
"encoding/json"
"errors"
"github.com/cloudflare/cfssl/api/generator"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/cli/genkey"
"github.com/cloudflare/cfssl/cli/sign"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/initca"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/signer"
)
var gencertUsageText = `cfssl gencert -- generate a new key and signed certificate
Usage of gencert:
Generate a new key and cert from CSR:
cfssl gencert -initca CSRJSON
cfssl gencert -ca cert -ca-key key [-config config] [-profile profile] [-hostname hostname] CSRJSON
cfssl gencert -remote remote_host [-config config] [-profile profile] [-label label] [-hostname hostname] CSRJSON
Re-generate a CA cert with the CA key and CSR:
cfssl gencert -initca -ca-key key CSRJSON
Re-generate a CA cert with the CA key and certificate:
cfssl gencert -renewca -ca cert -ca-key key
Arguments:
CSRJSON: JSON file containing the request, use '-' for reading JSON from stdin
Flags:
`
var gencertFlags = []string{"initca", "remote", "ca", "ca-key", "config", "cn", "hostname", "profile", "label"}
func gencertMain(args []string, c cli.Config) error {
if c.RenewCA {
log.Infof("re-generate a CA certificate from CA cert and key")
cert, err := initca.RenewFromPEM(c.CAFile, c.CAKeyFile)
if err != nil {
log.Errorf("%v\n", err)
return err
}
cli.PrintCert(nil, nil, cert)
return nil
}
csrJSONFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return err
}
if len(args) > 0 {
return errors.New("only one argument is accepted, please check with usage")
}
csrJSONFileBytes, err := cli.ReadStdin(csrJSONFile)
if err != nil {
return err
}
req := csr.CertificateRequest{
KeyRequest: csr.NewBasicKeyRequest(),
}
err = json.Unmarshal(csrJSONFileBytes, &req)
if err != nil {
return err
}
if c.CNOverride != "" {
req.CN = c.CNOverride
}
switch {
case c.IsCA:
var key, csrPEM, cert []byte
if c.CAKeyFile != "" {
log.Infof("re-generate a CA certificate from CSR and CA key")
cert, csrPEM, err = initca.NewFromPEM(&req, c.CAKeyFile)
if err != nil {
log.Errorf("%v\n", err)
return err
}
} else {
log.Infof("generating a new CA key and certificate from CSR")
cert, csrPEM, key, err = initca.New(&req)
if err != nil {
return err
}
}
cli.PrintCert(key, csrPEM, cert)
default:
if req.CA != nil {
err = errors.New("ca section only permitted in initca")
return err
}
if c.Hostname != "" {
req.Hosts = signer.SplitHosts(c.Hostname)
}
// Remote can be forced on the command line or in the config
if c.Remote == "" && c.CFG == nil {
if c.CAFile == "" {
log.Error("need a CA certificate (provide one with -ca)")
return nil
}
if c.CAKeyFile == "" {
log.Error("need a CA key (provide one with -ca-key)")
return nil
}
}
var key, csrBytes []byte
g := &csr.Generator{Validator: genkey.Validator}
csrBytes, key, err = g.ProcessRequest(&req)
if err != nil {
key = nil
return err
}
s, err := sign.SignerFromConfig(c)
if err != nil {
return err
}
var cert []byte
signReq := signer.SignRequest{
Request: string(csrBytes),
Hosts: signer.SplitHosts(c.Hostname),
Profile: c.Profile,
Label: c.Label,
}
if c.CRL != "" {
signReq.CRLOverride = c.CRL
}
cert, err = s.Sign(signReq)
if err != nil {
return err
}
// This follows the Baseline Requirements for the Issuance and
// Management of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser
// Forum (https://cabforum.org). Specifically, section 10.2.3 ("Information
// Requirements"), states:
//
// "Applicant information MUST include, but not be limited to, at least one
// Fully-Qualified Domain Name or IP address to be included in the Certificates
// SubjectAltName extension."
if len(signReq.Hosts) == 0 && len(req.Hosts) == 0 {
log.Warning(generator.CSRNoHostMessage)
}
cli.PrintCert(key, csrBytes, cert)
}
return nil
}
// Command assembles the definition of Command 'gencert'
var Command = &cli.Command{UsageText: gencertUsageText, Flags: gencertFlags, Main: gencertMain}

View File

@ -1,27 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gencrl.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/gencrl",
importpath = "github.com/cloudflare/cfssl/cli/gencrl",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/crl:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,82 +0,0 @@
//Package gencrl implements the gencrl command
package gencrl
import (
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/crl"
"strings"
)
var gencrlUsageText = `cfssl gencrl -- generate a new Certificate Revocation List
Usage of gencrl:
cfssl gencrl INPUTFILE CERT KEY TIME
Arguments:
INPUTFILE: Text file with one serial number per line, use '-' for reading text from stdin
CERT: The certificate that is signing this CRL, use '-' for reading text from stdin
KEY: The private key of the certificate that is signing the CRL, use '-' for reading text from stdin
TIME (OPTIONAL): The desired expiration from now, in seconds
Flags:
`
var gencrlFlags = []string{}
func gencrlMain(args []string, c cli.Config) (err error) {
serialList, args, err := cli.PopFirstArgument(args)
if err != nil {
return
}
serialListBytes, err := cli.ReadStdin(serialList)
if err != nil {
return
}
certFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return
}
certFileBytes, err := cli.ReadStdin(certFile)
if err != nil {
return
}
keyFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return
}
keyBytes, err := cli.ReadStdin(keyFile)
if err != nil {
return
}
// Default value if no expiry time is given
timeString := string("0")
if len(args) > 0 {
timeArg, _, err := cli.PopFirstArgument(args)
if err != nil {
return err
}
timeString = string(timeArg)
// This is used to get rid of newlines
timeString = strings.TrimSpace(timeString)
}
req, err := crl.NewCRLFromFile(serialListBytes, certFileBytes, keyBytes, timeString)
if err != nil {
return
}
cli.PrintCRL(req)
return nil
}
// Command assembles the definition of Command 'gencrl'
var Command = &cli.Command{UsageText: gencrlUsageText, Flags: gencrlFlags, Main: gencrlMain}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["gencsr.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/gencsr",
importpath = "github.com/cloudflare/cfssl/cli/gencsr",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/signer:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,99 +0,0 @@
// Package gencsr implements the gencsr command.
package gencsr
import (
"encoding/json"
"errors"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/signer"
)
var gencsrUsageText = `cfssl gencsr -- generate a csr from a private key with existing CSR json specification or certificate
Usage of genkey:
cfssl gencsr -key private_key_file [-host hostname_override] CSRJSON
cfssl gencsr -key private_key_file [-host hostname_override] -cert certificate_file
Arguments:
CSRJSON: JSON file containing the request, use '-' for reading JSON from stdin
Flags:
`
var gencsrFlags = []string{"key", "cert"}
func gencsrMain(args []string, c cli.Config) (err error) {
if c.KeyFile == "" {
return errors.New("private key file is required through '-key', please check with usage")
}
keyBytes, err := helpers.ReadBytes(c.KeyFile)
if err != nil {
return err
}
key, err := helpers.ParsePrivateKeyPEM(keyBytes)
if err != nil {
return err
}
// prepare a stub CertificateRequest
req := &csr.CertificateRequest{
KeyRequest: csr.NewBasicKeyRequest(),
}
if c.CertFile != "" {
if len(args) > 0 {
return errors.New("no argument is accepted with '-cert', please check with usage")
}
certBytes, err := helpers.ReadBytes(c.CertFile)
if err != nil {
return err
}
cert, err := helpers.ParseCertificatePEM(certBytes)
if err != nil {
return err
}
req = csr.ExtractCertificateRequest(cert)
} else {
csrFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return err
}
if len(args) > 0 {
return errors.New("only one argument is accepted, please check with usage")
}
csrFileBytes, err := cli.ReadStdin(csrFile)
if err != nil {
return err
}
err = json.Unmarshal(csrFileBytes, req)
if err != nil {
return err
}
}
if c.Hostname != "" {
req.Hosts = signer.SplitHosts(c.Hostname)
}
csrBytes, err := csr.Generate(key, req)
if err != nil {
return err
}
cli.PrintCert(keyBytes, csrBytes, nil)
return nil
}
// Command assembles the definition of Command 'gencsr'
var Command = &cli.Command{UsageText: gencsrUsageText, Flags: gencsrFlags, Main: gencsrMain}

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["genkey.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/genkey",
importpath = "github.com/cloudflare/cfssl/cli/genkey",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/initca:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,82 +0,0 @@
// Package genkey implements the genkey command.
package genkey
import (
"encoding/json"
"errors"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/initca"
)
var genkeyUsageText = `cfssl genkey -- generate a new key and CSR
Usage of genkey:
cfssl genkey CSRJSON
Arguments:
CSRJSON: JSON file containing the request, use '-' for reading JSON from stdin
Flags:
`
var genkeyFlags = []string{"initca", "config"}
func genkeyMain(args []string, c cli.Config) (err error) {
csrFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return
}
if len(args) > 0 {
return errors.New("only one argument is accepted, please check with usage")
}
csrFileBytes, err := cli.ReadStdin(csrFile)
if err != nil {
return
}
req := csr.CertificateRequest{
KeyRequest: csr.NewBasicKeyRequest(),
}
err = json.Unmarshal(csrFileBytes, &req)
if err != nil {
return
}
if c.IsCA {
var key, csrPEM, cert []byte
cert, csrPEM, key, err = initca.New(&req)
if err != nil {
return
}
cli.PrintCert(key, csrPEM, cert)
} else {
if req.CA != nil {
err = errors.New("ca section only permitted in initca")
return
}
var key, csrPEM []byte
g := &csr.Generator{Validator: Validator}
csrPEM, key, err = g.ProcessRequest(&req)
if err != nil {
key = nil
return
}
cli.PrintCert(key, csrPEM, nil)
}
return nil
}
// Validator does nothing and will never return an error. It exists because creating a
// csr.Generator requires a Validator.
func Validator(req *csr.CertificateRequest) error {
return nil
}
// Command assembles the definition of Command 'genkey'
var Command = &cli.Command{UsageText: genkeyUsageText, Flags: genkeyFlags, Main: genkeyMain}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["info.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/info",
importpath = "github.com/cloudflare/cfssl/cli/info",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/api/client:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli/sign:go_default_library",
"//vendor/github.com/cloudflare/cfssl/errors:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/info:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,110 +0,0 @@
// Package info implements the info command.
package info
import (
"encoding/json"
"fmt"
"github.com/cloudflare/cfssl/api/client"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/cli/sign"
"github.com/cloudflare/cfssl/errors"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/info"
goerr "errors"
)
var infoUsageTxt = `cfssl info -- get info about a remote signer
Usage:
Get info about a remote signer:
cfssl info -remote remote_host [-label label] [-profile profile] [-label label]
Flags:
`
var infoFlags = []string{"remote", "label", "profile", "config"}
func getInfoFromRemote(c cli.Config) (resp *info.Resp, err error) {
req := new(info.Req)
req.Label = c.Label
req.Profile = c.Profile
cert, err := helpers.LoadClientCertificate(c.MutualTLSCertFile, c.MutualTLSKeyFile)
if err != nil {
return
}
remoteCAs, err := helpers.LoadPEMCertPool(c.TLSRemoteCAs)
if err != nil {
return
}
serv := client.NewServerTLS(c.Remote, helpers.CreateTLSConfig(remoteCAs, cert))
reqJSON, _ := json.Marshal(req)
resp, err = serv.Info(reqJSON)
if err != nil {
return
}
_, err = helpers.ParseCertificatePEM([]byte(resp.Certificate))
if err != nil {
return
}
return
}
func getInfoFromConfig(c cli.Config) (resp *info.Resp, err error) {
s, err := sign.SignerFromConfig(c)
if err != nil {
return
}
req := new(info.Req)
req.Label = c.Label
req.Profile = c.Profile
resp, err = s.Info(*req)
if err != nil {
return
}
return
}
func infoMain(args []string, c cli.Config) (err error) {
if len(args) > 0 {
return goerr.New("argument is provided but not defined; please refer to the usage by flag -h.")
}
var resp *info.Resp
if c.Remote != "" {
resp, err = getInfoFromRemote(c)
if err != nil {
return
}
} else if c.CFG != nil {
resp, err = getInfoFromConfig(c)
if err != nil {
return
}
} else {
return goerr.New("Either -remote or -config must be given. Refer to cfssl info -h for usage.")
}
respJSON, err := json.Marshal(resp)
if err != nil {
return errors.NewBadRequest(err)
}
fmt.Print(string(respJSON))
return nil
}
// Command assembles the definition of Command 'info'
var Command = &cli.Command{
UsageText: infoUsageTxt,
Flags: infoFlags,
Main: infoMain,
}

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ocspdump.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/ocspdump",
importpath = "github.com/cloudflare/cfssl/cli/ocspdump",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certdb/dbconf:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb/sql:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,50 +0,0 @@
// Package ocspdump implements the ocspdump command.
package ocspdump
import (
"encoding/base64"
"errors"
"fmt"
"github.com/cloudflare/cfssl/certdb/dbconf"
"github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/cli"
)
// Usage text of 'cfssl ocspdump'
var ocspdumpUsageText = `cfssl ocspdump -- generates a series of concatenated OCSP responses
for use with ocspserve from all OCSP responses in the cert db
Usage of ocspdump:
cfssl ocspdump -db-config db-config
Flags:
`
// Flags of 'cfssl ocspdump'
var ocspdumpFlags = []string{"db-config"}
// ocspdumpMain is the main CLI of OCSP dump functionality.
func ocspdumpMain(args []string, c cli.Config) error {
if c.DBConfigFile == "" {
return errors.New("need DB config file (provide with -db-config)")
}
db, err := dbconf.DBFromConfig(c.DBConfigFile)
if err != nil {
return err
}
dbAccessor := sql.NewAccessor(db)
records, err := dbAccessor.GetUnexpiredOCSPs()
if err != nil {
return err
}
for _, certRecord := range records {
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString([]byte(certRecord.Body)))
}
return nil
}
// Command assembles the definition of Command 'ocspdump'
var Command = &cli.Command{UsageText: ocspdumpUsageText, Flags: ocspdumpFlags, Main: ocspdumpMain}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ocsprefresh.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/ocsprefresh",
importpath = "github.com/cloudflare/cfssl/cli/ocsprefresh",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certdb/dbconf:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb/sql:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,112 +0,0 @@
// Package ocsprefresh implements the ocsprefresh command.
package ocsprefresh
import (
"encoding/hex"
"errors"
"time"
"github.com/cloudflare/cfssl/certdb/dbconf"
"github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
// Usage text of 'cfssl ocsprefresh'
var ocsprefreshUsageText = `cfssl ocsprefresh -- refreshes the ocsp_responses table
with new OCSP responses for all known unexpired certificates
Usage of ocsprefresh:
cfssl ocsprefresh -db-config db-config -ca cert -responder cert -responder-key key [-interval 96h]
Flags:
`
// Flags of 'cfssl ocsprefresh'
var ocsprefreshFlags = []string{"ca", "responder", "responder-key", "db-config", "interval"}
// ocsprefreshMain is the main CLI of OCSP refresh functionality.
func ocsprefreshMain(args []string, c cli.Config) error {
if c.DBConfigFile == "" {
return errors.New("need DB config file (provide with -db-config)")
}
if c.ResponderFile == "" {
return errors.New("need responder certificate (provide with -responder)")
}
if c.ResponderKeyFile == "" {
return errors.New("need responder key (provide with -responder-key)")
}
if c.CAFile == "" {
return errors.New("need CA certificate (provide with -ca)")
}
s, err := SignerFromConfig(c)
if err != nil {
log.Critical("Unable to create OCSP signer: ", err)
return err
}
db, err := dbconf.DBFromConfig(c.DBConfigFile)
if err != nil {
return err
}
dbAccessor := sql.NewAccessor(db)
certs, err := dbAccessor.GetUnexpiredCertificates()
if err != nil {
return err
}
// Set an expiry timestamp for all certificates refreshed in this batch
ocspExpiry := time.Now().Add(c.Interval)
for _, certRecord := range certs {
cert, err := helpers.ParseCertificatePEM([]byte(certRecord.PEM))
if err != nil {
log.Critical("Unable to parse certificate: ", err)
return err
}
req := ocsp.SignRequest{
Certificate: cert,
Status: certRecord.Status,
}
if certRecord.Status == "revoked" {
req.Reason = int(certRecord.Reason)
req.RevokedAt = certRecord.RevokedAt
}
resp, err := s.Sign(req)
if err != nil {
log.Critical("Unable to sign OCSP response: ", err)
return err
}
err = dbAccessor.UpsertOCSP(cert.SerialNumber.String(), hex.EncodeToString(cert.AuthorityKeyId), string(resp), ocspExpiry)
if err != nil {
log.Critical("Unable to save OCSP response: ", err)
return err
}
}
return nil
}
// SignerFromConfig creates a signer from a cli.Config as a helper for cli and serve
func SignerFromConfig(c cli.Config) (ocsp.Signer, error) {
//if this is called from serve then we need to use the specific responder key file
//fallback to key for backwards-compatibility
k := c.ResponderKeyFile
if k == "" {
k = c.KeyFile
}
return ocsp.NewSignerFromFile(c.CAFile, c.ResponderFile, k, time.Duration(c.Interval))
}
// Command assembles the definition of Command 'ocsprefresh'
var Command = &cli.Command{UsageText: ocsprefreshUsageText, Flags: ocsprefreshFlags, Main: ocsprefreshMain}

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ocspserve.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/ocspserve",
importpath = "github.com/cloudflare/cfssl/cli/ocspserve",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,62 +0,0 @@
// Package ocspserve implements the ocspserve function.
package ocspserve
import (
"errors"
"fmt"
"net/http"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
// Usage text of 'cfssl serve'
var ocspServerUsageText = `cfssl ocspserve -- set up an HTTP server that handles OCSP requests from either a file or directly from a database (see RFC 5019)
Usage of ocspserve:
cfssl ocspserve [-address address] [-port port] [-responses file] [-db-config db-config]
Flags:
`
// Flags used by 'cfssl serve'
var ocspServerFlags = []string{"address", "port", "responses", "db-config"}
// ocspServerMain is the command line entry point to the OCSP responder.
// It sets up a new HTTP server that responds to OCSP requests.
func ocspServerMain(args []string, c cli.Config) error {
var src ocsp.Source
// serve doesn't support arguments.
if len(args) > 0 {
return errors.New("argument is provided but not defined; please refer to the usage by flag -h")
}
if c.Responses != "" {
s, err := ocsp.NewSourceFromFile(c.Responses)
if err != nil {
return errors.New("unable to read response file")
}
src = s
} else if c.DBConfigFile != "" {
s, err := ocsp.NewSourceFromDB(c.DBConfigFile)
if err != nil {
return errors.New("unable to read configuration file")
}
src = s
} else {
return errors.New(
"no response file or db-config provided, please set the one of these using either -responses or -db-config flags",
)
}
log.Info("Registering OCSP responder handler")
http.Handle(c.Path, ocsp.NewResponder(src))
addr := fmt.Sprintf("%s:%d", c.Address, c.Port)
log.Info("Now listening on ", addr)
return http.ListenAndServe(addr, nil)
}
// Command assembles the definition of Command 'ocspserve'
var Command = &cli.Command{UsageText: ocspServerUsageText, Flags: ocspServerFlags, Main: ocspServerMain}

View File

@ -1,29 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["ocspsign.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/ocspsign",
importpath = "github.com/cloudflare/cfssl/cli/ocspsign",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,93 +0,0 @@
// Package ocspsign implements the ocspsign command.
package ocspsign
import (
"io/ioutil"
"time"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
// Usage text of 'cfssl ocspsign'
var ocspSignerUsageText = `cfssl ocspsign -- signs an OCSP response for a given CA, cert, and status.
Returns a base64-encoded OCSP response.
Usage of ocspsign:
cfssl ocspsign -ca cert -responder cert -responder-key key -cert cert [-status status] [-reason code] [-revoked-at YYYY-MM-DD] [-interval 96h]
Flags:
`
// Flags of 'cfssl ocspsign'
var ocspSignerFlags = []string{"ca", "responder", "responder-key", "reason", "status", "revoked-at", "interval"}
// ocspSignerMain is the main CLI of OCSP signer functionality.
func ocspSignerMain(args []string, c cli.Config) (err error) {
// Read the cert to be revoked from file
certBytes, err := ioutil.ReadFile(c.CertFile)
if err != nil {
log.Critical("Unable to read certificate: ", err)
return
}
cert, err := helpers.ParseCertificatePEM(certBytes)
if err != nil {
log.Critical("Unable to parse certificate: ", err)
return
}
req := ocsp.SignRequest{
Certificate: cert,
Status: c.Status,
}
if c.Status == "revoked" {
var reasonCode int
reasonCode, err = ocsp.ReasonStringToCode(c.Reason)
if err != nil {
log.Critical("Invalid reason code: ", err)
return
}
req.Reason = reasonCode
req.RevokedAt = time.Now()
if c.RevokedAt != "now" {
req.RevokedAt, err = time.Parse("2006-01-02", c.RevokedAt)
if err != nil {
log.Critical("Malformed revocation time: ", c.RevokedAt)
return
}
}
}
s, err := SignerFromConfig(c)
if err != nil {
log.Critical("Unable to create OCSP signer: ", err)
return
}
resp, err := s.Sign(req)
if err != nil {
log.Critical("Unable to sign OCSP response: ", err)
return
}
cli.PrintOCSPResponse(resp)
return
}
// SignerFromConfig creates a signer from a cli.Config as a helper for cli and serve
func SignerFromConfig(c cli.Config) (ocsp.Signer, error) {
//if this is called from serve then we need to use the specific responder key file
//fallback to key for backwards-compatibility
k := c.ResponderKeyFile
if k == "" {
k = c.KeyFile
}
return ocsp.NewSignerFromFile(c.CAFile, c.ResponderFile, k, time.Duration(c.Interval))
}
// Command assembles the definition of Command 'ocspsign'
var Command = &cli.Command{UsageText: ocspSignerUsageText, Flags: ocspSignerFlags, Main: ocspSignerMain}

View File

@ -1,27 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"defaults.go",
"printdefault.go",
],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/printdefault",
importpath = "github.com/cloudflare/cfssl/cli/printdefault",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/cloudflare/cfssl/cli:go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,49 +0,0 @@
package printdefaults
var defaults = map[string]string{
"config": `{
"signing": {
"default": {
"expiry": "168h"
},
"profiles": {
"www": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "8760h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
}
}
}
}
`,
"csr": `{
"CN": "example.net",
"hosts": [
"example.net",
"www.example.net"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"ST": "CA",
"L": "San Francisco"
}
]
}
`,
}

View File

@ -1,48 +0,0 @@
package printdefaults
import (
"fmt"
"github.com/cloudflare/cfssl/cli"
)
var printDefaultsUsage = `cfssl print-defaults -- print default configurations that can be used as a template
Usage of print-defaults:
cfssl print-defaults TYPE
If "list" is used as the TYPE, the list of supported types will be printed.
`
func printAvailable() {
fmt.Println("Default configurations are available for:")
for name := range defaults {
fmt.Println("\t" + name)
}
}
func printDefaults(args []string, c cli.Config) (err error) {
arg, _, err := cli.PopFirstArgument(args)
if err != nil {
return
}
if arg == "list" {
printAvailable()
} else {
if config, ok := defaults[arg]; !ok {
printAvailable()
} else {
fmt.Println(config)
}
}
return
}
// Command assembles the definition of Command 'print-defaults'
var Command = &cli.Command{
UsageText: printDefaultsUsage,
Flags: []string{},
Main: printDefaults,
}

View File

@ -1,30 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["revoke.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/revoke",
importpath = "github.com/cloudflare/cfssl/cli/revoke",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/certdb/dbconf:go_default_library",
"//vendor/github.com/cloudflare/cfssl/certdb/sql:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/ocsp:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,66 +0,0 @@
// Package revoke implements the revoke command.
package revoke
import (
"errors"
"github.com/cloudflare/cfssl/certdb/dbconf"
"github.com/cloudflare/cfssl/certdb/sql"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/ocsp"
)
var revokeUsageTxt = `cfssl revoke -- revoke a certificate in the certificate store
Usage:
Revoke a certificate:
cfssl revoke -db-config config_file -serial serial -aki authority_key_id [-reason reason]
Reason can be an integer code or a string in ReasonFlags in RFC 5280
Flags:
`
var revokeFlags = []string{"serial", "reason"}
func revokeMain(args []string, c cli.Config) error {
if len(args) > 0 {
return errors.New("argument is provided but not defined; please refer to the usage by flag -h")
}
if len(c.Serial) == 0 {
return errors.New("serial number is required but not provided")
}
if len(c.AKI) == 0 {
return errors.New("authority key id is required but not provided")
}
if c.DBConfigFile == "" {
return errors.New("need DB config file (provide with -db-config)")
}
db, err := dbconf.DBFromConfig(c.DBConfigFile)
if err != nil {
return err
}
dbAccessor := sql.NewAccessor(db)
reasonCode, err := ocsp.ReasonStringToCode(c.Reason)
if err != nil {
log.Error("Invalid reason code: ", err)
return err
}
return dbAccessor.RevokeCertificate(c.Serial, c.AKI, reasonCode)
}
// Command assembles the definition of Command 'revoke'
var Command = &cli.Command{
UsageText: revokeUsageTxt,
Flags: revokeFlags,
Main: revokeMain,
}

View File

@ -1,28 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["scan.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/scan",
importpath = "github.com/cloudflare/cfssl/cli/scan",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/log:go_default_library",
"//vendor/github.com/cloudflare/cfssl/scan:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,123 +0,0 @@
package scan
import (
"encoding/csv"
"encoding/json"
"fmt"
"io"
"os"
"sync"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/log"
"github.com/cloudflare/cfssl/scan"
)
var scanUsageText = `cfssl scan -- scan a host for issues
Usage of scan:
cfssl scan [-family regexp] [-scanner regexp] [-timeout duration] [-ip IPAddr] [-num-workers num] [-max-hosts num] [-csv hosts.csv] HOST+
cfssl scan -list
Arguments:
HOST: Host(s) to scan (including port)
Flags:
`
var scanFlags = []string{"list", "family", "scanner", "timeout", "ip", "ca-bundle", "num-workers", "csv", "max-hosts"}
func printJSON(v interface{}) {
b, err := json.MarshalIndent(v, "", " ")
if err != nil {
fmt.Println(err)
}
fmt.Printf("%s\n\n", b)
}
type context struct {
sync.WaitGroup
c cli.Config
hosts chan string
}
func newContext(c cli.Config, numWorkers int) *context {
ctx := &context{
c: c,
hosts: make(chan string, numWorkers),
}
ctx.Add(numWorkers)
for i := 0; i < numWorkers; i++ {
go ctx.runWorker()
}
return ctx
}
func (ctx *context) runWorker() {
for host := range ctx.hosts {
fmt.Printf("Scanning %s...\n", host)
results, err := scan.Default.RunScans(host, ctx.c.IP, ctx.c.Family, ctx.c.Scanner, ctx.c.Timeout)
fmt.Printf("=== %s ===\n", host)
if err != nil {
log.Error(err)
} else {
printJSON(results)
}
}
ctx.Done()
}
func parseCSV(hosts []string, csvFile string, maxHosts int) ([]string, error) {
f, err := os.Open(csvFile)
if err != nil {
return nil, err
}
defer f.Close()
r := csv.NewReader(f)
for err == nil && len(hosts) < maxHosts {
var record []string
record, err = r.Read()
hosts = append(hosts, record[len(record)-1])
}
if err == io.EOF {
err = nil
}
return hosts, err
}
func scanMain(args []string, c cli.Config) (err error) {
if c.List {
printJSON(scan.Default)
} else {
if err = scan.LoadRootCAs(c.CABundleFile); err != nil {
return
}
if len(args) >= c.MaxHosts {
log.Warningf("Only scanning max-hosts=%d out of %d args given", c.MaxHosts, len(args))
args = args[:c.MaxHosts]
} else if c.CSVFile != "" {
args, err = parseCSV(args, c.CSVFile, c.MaxHosts)
if err != nil {
return
}
}
ctx := newContext(c, c.NumWorkers)
// Execute for each HOST argument given
for len(args) > 0 {
var host string
host, args, err = cli.PopFirstArgument(args)
if err != nil {
return
}
ctx.hosts <- host
}
close(ctx.hosts)
ctx.Wait()
}
return
}
// Command assembles the definition of Command 'scan'
var Command = &cli.Command{UsageText: scanUsageText, Flags: scanFlags, Main: scanMain}

View File

@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["selfsign.go"],
importmap = "k8s.io/kubernetes/vendor/github.com/cloudflare/cfssl/cli/selfsign",
importpath = "github.com/cloudflare/cfssl/cli/selfsign",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/cloudflare/cfssl/cli:go_default_library",
"//vendor/github.com/cloudflare/cfssl/cli/genkey:go_default_library",
"//vendor/github.com/cloudflare/cfssl/config:go_default_library",
"//vendor/github.com/cloudflare/cfssl/csr:go_default_library",
"//vendor/github.com/cloudflare/cfssl/helpers:go_default_library",
"//vendor/github.com/cloudflare/cfssl/selfsign:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -1,120 +0,0 @@
// Package selfsign implements the selfsign command.
package selfsign
import (
"encoding/json"
"errors"
"fmt"
"os"
"time"
"github.com/cloudflare/cfssl/cli"
"github.com/cloudflare/cfssl/cli/genkey"
"github.com/cloudflare/cfssl/config"
"github.com/cloudflare/cfssl/csr"
"github.com/cloudflare/cfssl/helpers"
"github.com/cloudflare/cfssl/selfsign"
)
var selfSignUsageText = `cfssl selfsign -- generate a new self-signed key and signed certificate
Usage of gencert:
cfssl selfsign HOSTNAME CSRJSON
WARNING: this should ONLY be used for testing. This should never be
used in production.
WARNING: self-signed certificates are insecure; they do not provide
the authentication required for secure systems. Use these at your own
risk.
Arguments:
HOSTNAME: Hostname for the cert
CSRJSON: JSON file containing the request, use '-' for reading JSON from stdin
Flags:
`
var selfSignFlags = []string{"config"}
func selfSignMain(args []string, c cli.Config) (err error) {
if c.Hostname == "" && !c.IsCA {
c.Hostname, args, err = cli.PopFirstArgument(args)
if err != nil {
return
}
}
csrFile, args, err := cli.PopFirstArgument(args)
if err != nil {
return
}
if len(args) > 0 {
return errors.New("too many arguments are provided, please check with usage")
}
csrFileBytes, err := cli.ReadStdin(csrFile)
if err != nil {
return
}
var req = csr.New()
err = json.Unmarshal(csrFileBytes, req)
if err != nil {
return
}
var key, csrPEM []byte
g := &csr.Generator{Validator: genkey.Validator}
csrPEM, key, err = g.ProcessRequest(req)
if err != nil {
key = nil
return
}
priv, err := helpers.ParsePrivateKeyPEM(key)
if err != nil {
key = nil
return
}
var profile *config.SigningProfile
// If there is a config, use its signing policy. Otherwise, leave policy == nil
// and NewSigner will use DefaultConfig().
if c.CFG != nil {
if c.Profile != "" && c.CFG.Signing.Profiles != nil {
profile = c.CFG.Signing.Profiles[c.Profile]
}
}
if profile == nil {
profile = config.DefaultConfig()
profile.Expiry = 2190 * time.Hour
}
cert, err := selfsign.Sign(priv, csrPEM, profile)
if err != nil {
key = nil
priv = nil
return
}
fmt.Fprintf(os.Stderr, `*** WARNING ***
Self-signed certificates are dangerous. Use this self-signed
certificate at your own risk.
It is strongly recommended that these certificates NOT be used
in production.
*** WARNING ***
`)
cli.PrintCert(key, csrPEM, cert)
return
}
// Command assembles the definition of Command 'selfsign'
var Command = &cli.Command{UsageText: selfSignUsageText, Flags: selfSignFlags, Main: selfSignMain}

Some files were not shown because too many files have changed in this diff Show More