k8sCertsFlatify 0.1.0-universal-linux
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README +7 -0
- data/bin/k8sCertsFlatify.rb +142 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 60516c53924fea13e7ec6a4b244942bdf1b413434a4baafa5a45bc34d09190d4
|
4
|
+
data.tar.gz: 773342e530314e16e1b6f365482ebe836a4b007f14099ad2efc4585b1ee8357a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 79a8f0b49a9891ad41c59842cabff067c8895b5f258fc0fa20a39fd1e73ad320f7c062b21a347b299c39a13c766ca3cda499ccd6aba5f834cbbb263f36432189
|
7
|
+
data.tar.gz: dd67c748b2f549151a7e3b8a57fae375864f7f918f0ff2aaa9c0cf282ffa86c602ed1475934783ad72b6d89e0278e0a809f5f7ae8a2c57a7ec07925c8b71dceb
|
data/README
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
A script which extracts 1 or multiple tls/ssl certificates from a kubernetes cluster to PWD.
|
2
|
+
NOTE: Will not check the TLS certificate of the connecting kubernetes cluster as of the current time.
|
3
|
+
Switch --kubeconfig/-c <kubernetes kubeconfig file>. If not present default to ~/.kube/config
|
4
|
+
switch --namespaces/-n -- Namespace to dump certificates in. If not present, will dump certificates of all namespaces.
|
5
|
+
--context/-k -- The context to use in the kubeconfig file.
|
6
|
+
--dumpdir/-d -- Dump certificates to this directory instead of PWD
|
7
|
+
Will dump certificates in PWD in a directory with the name as the DNS to which the certificate belongs.
|
@@ -0,0 +1,142 @@
|
|
1
|
+
#! /usr/bin/ruby
|
2
|
+
# NOTE: Will not check the TLS certificate of the connecting kubernetes cluster as of the current time.
|
3
|
+
require 'curb'
|
4
|
+
require 'oj'
|
5
|
+
require 'base64'
|
6
|
+
require 'fileutils.rb'
|
7
|
+
require 'optparse'
|
8
|
+
require 'kubeclient'
|
9
|
+
|
10
|
+
# Stores options as passed in switches to the script
|
11
|
+
@switchOptions = Hash.new
|
12
|
+
opts = OptionParser.new
|
13
|
+
kubecfg = nil
|
14
|
+
opts.banner = "Dump certificates which exists in a Kubernetes cluster to flat files in PWD."
|
15
|
+
opts.on('-k', '--context CONTEXT', 'The context to use in the kubeconfig file.') {
|
16
|
+
|kubecontext|
|
17
|
+
@switchOptions[:context] = kubecontext
|
18
|
+
}
|
19
|
+
opts.on('-c', '--kubeconfig KUBECONFIG', 'If not present default to ~/.kube/config') {
|
20
|
+
|kubeconfig|
|
21
|
+
kubecfg = kubeconfig
|
22
|
+
}
|
23
|
+
opts.on('-n', '--namespaces NAMESPACE', 'Namespace to dump certificates in. If not present, will dump certificates of all namespaces.') {
|
24
|
+
|ns|
|
25
|
+
@switchOptions[:ns] = ns
|
26
|
+
}
|
27
|
+
opts.on('-d', '--dumpdir DIR', 'Dump certificates to this directory instead of PWD') {
|
28
|
+
|dir|
|
29
|
+
Dir.chdir(dir)
|
30
|
+
}
|
31
|
+
opts.parse!
|
32
|
+
|
33
|
+
kubecfg = "#{ENV['HOME']}/.kube/config" if kubecfg == nil
|
34
|
+
if @switchOptions[:context] == nil
|
35
|
+
kubeContext = Kubeclient::Config.read(kubecfg).context
|
36
|
+
else
|
37
|
+
kubeContext = Kubeclient::Config.read(kubecfg).context(@switchOptions[:context])
|
38
|
+
end
|
39
|
+
@bearer = "Bearer #{kubeContext.auth_options[:bearer_token]}"
|
40
|
+
# API endpoint templates for all ingress
|
41
|
+
@allingendpoint = "apis/networking.k8s.io/v1/ingresses"
|
42
|
+
# API endpoint templates for single ingress
|
43
|
+
@aningendpoint = "apis/networking.k8s.io/v1/namespaces/$${namespace}/ingresses"
|
44
|
+
# old k8s
|
45
|
+
# @allingendpoint = "apis/networking.k8s.io/v1beta1/ingresses"
|
46
|
+
@secendpoint = "api/v1/namespaces/$${namespace}/secrets/$${name}"
|
47
|
+
@server = kubeContext.api_endpoint
|
48
|
+
# TODO: Could not get CA certificate.
|
49
|
+
# puts kubeContext.ssl_options[:cert_store].class
|
50
|
+
# GC
|
51
|
+
kubeContext = nil
|
52
|
+
kubecfg = nil
|
53
|
+
|
54
|
+
|
55
|
+
# TODO: Could not get CA certificate.
|
56
|
+
@ca = nil
|
57
|
+
allinghash = String.new
|
58
|
+
Oj.default_options = { :symbol_keys => true, :bigdecimal_as_decimal => true, :mode => :compat, 'load' => :compat }
|
59
|
+
|
60
|
+
# will return an array. First element being the certificate, 2nd the secret. Will return false in case of issues (like secrets does not hold a certificate)
|
61
|
+
def getCerts(name, namespace)
|
62
|
+
if name.class != String
|
63
|
+
puts "name not present for namespace #{namespace}"
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
if namespace.class != String
|
67
|
+
puts "namespace not present for name #{name}"
|
68
|
+
return nil
|
69
|
+
end
|
70
|
+
endpoint = @secendpoint.dup
|
71
|
+
endpoint.gsub!(%r{\$\$\{name\}}, name)
|
72
|
+
endpoint.gsub!(%r{\$\$\{namespace\}}, namespace)
|
73
|
+
thesec = String.new
|
74
|
+
k8sconnection = Curl::Easy.new(@server + endpoint) {
|
75
|
+
|request|
|
76
|
+
request.headers = { :Authorization => @bearer }
|
77
|
+
# TODO: Could not get CA certificate.
|
78
|
+
# request.cacert = @ca
|
79
|
+
request.ssl_verify_host = false
|
80
|
+
request.ssl_verify_peer = false
|
81
|
+
request.http_get
|
82
|
+
thesec = Oj.load(request.body_str)
|
83
|
+
}
|
84
|
+
if thesec[:type] != 'kubernetes.io/tls'
|
85
|
+
puts "Secret with name #{name} in namespace #{namespace} is not of type kubernetes.io/tls"
|
86
|
+
return nil
|
87
|
+
end
|
88
|
+
if (thesec[:data][:'tls.crt'] == nil || thesec[:data][:'tls.key'] == nil)
|
89
|
+
puts "tls.crt or/and tls.key keys in the secret is empty for secret #{namespace}/#{name}"
|
90
|
+
return nil
|
91
|
+
end
|
92
|
+
return [Base64.strict_decode64(thesec[:data][:'tls.crt']), Base64.strict_decode64(thesec[:data][:'tls.key'])]
|
93
|
+
end
|
94
|
+
|
95
|
+
# select endpoint based on mode of operation -- single certificate or all of them.
|
96
|
+
endpoint = nil
|
97
|
+
if @switchOptions[:ns] == nil
|
98
|
+
endpoint = @allingendpoint
|
99
|
+
else
|
100
|
+
endpoint = @aningendpoint.dup.gsub!(%r{\$\$\{namespace\}}, @switchOptions[:ns])
|
101
|
+
end
|
102
|
+
puts endpoint
|
103
|
+
k8sconnection = Curl::Easy.new(@server + endpoint) {
|
104
|
+
|request|
|
105
|
+
request.headers = { :Authorization => @bearer }
|
106
|
+
# TODO: Could not get CA certificate.
|
107
|
+
# request.cacert = @ca
|
108
|
+
request.ssl_verify_host = false
|
109
|
+
request.ssl_verify_peer = false
|
110
|
+
request.http_get
|
111
|
+
allinghash = Oj.load(request.body_str)
|
112
|
+
}
|
113
|
+
|
114
|
+
k8sconnection = nil
|
115
|
+
allinghash[:items].each {
|
116
|
+
|ingress|
|
117
|
+
ingNamespace = ingress[:metadata][:namespace]
|
118
|
+
if ingress == nil
|
119
|
+
puts "ingress entry was empty in namespace #{ingNamespace}"
|
120
|
+
elsif ingress[:spec] == nil
|
121
|
+
puts "ingress spec was empty for ingress #{ingress[:metadata][:name]} in namespace #{ingNamespace}"
|
122
|
+
elsif ingress[:spec][:tls] == nil
|
123
|
+
puts "No tls certificate specified in ingress #{ingress[:metadata][:name]} in namespace #{ingNamespace}"
|
124
|
+
elsif ingress[:spec][:tls].length >= 1
|
125
|
+
ingress[:spec][:tls].each {
|
126
|
+
|secretref|
|
127
|
+
if certpair = getCerts(secretref[:secretName], ingNamespace)
|
128
|
+
begin
|
129
|
+
FileUtils.mkdir(secretref[:hosts])
|
130
|
+
rescue Errno::EEXIST
|
131
|
+
end
|
132
|
+
secretref[:hosts].each {
|
133
|
+
|host|
|
134
|
+
IO.binwrite("#{host}/cert.crt", certpair[0])
|
135
|
+
IO.binwrite("#{host}/key.key", certpair[1])
|
136
|
+
}
|
137
|
+
end
|
138
|
+
}
|
139
|
+
else
|
140
|
+
puts "No TLS entry found for ingress #{ingress[:metadata][:name]} in namespace #{ingNamespace}"
|
141
|
+
end
|
142
|
+
}
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: k8sCertsFlatify
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: universal-linux
|
6
|
+
authors:
|
7
|
+
- dE
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: curb
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oj
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: kubeclient
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4'
|
55
|
+
description:
|
56
|
+
email: de.techno@gmail.com
|
57
|
+
executables:
|
58
|
+
- k8sCertsFlatify.rb
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- README
|
63
|
+
- bin/k8sCertsFlatify.rb
|
64
|
+
homepage: http://delogics.blogspot.com
|
65
|
+
licenses:
|
66
|
+
- Apache-2.0
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
requirements: []
|
83
|
+
rubygems_version: 3.4.22
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: A script which extracts 1 or multiple tls/ssl certificates from a kubernetes
|
87
|
+
cluster.
|
88
|
+
test_files: []
|