k8sCertsFlatify 0.1.0-universal-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/README +7 -0
  3. data/bin/k8sCertsFlatify.rb +142 -0
  4. 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: []