Skip to content

Commit aa77f9b

Browse files
committed
reload service account token within incluster config
1 parent af7b29c commit aa77f9b

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

kubernetes/spec/config/incluster_config_spec.rb

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
require 'kubernetes/config/incluster_config'
2020

21-
# rubocop:disable BlockLength
21+
# rubocop:disable Metrics/BlockLength
2222
describe Kubernetes::InClusterConfig do
2323
context '#configure' do
2424
let(:incluster_config) do
@@ -36,6 +36,10 @@
3636
:@token_file,
3737
Kubernetes::Testing.file_fixture('tokens/token').to_s
3838
)
39+
c.instance_variable_set(
40+
:@token_refresh_period,
41+
5
42+
)
3943
end
4044
end
4145

@@ -50,6 +54,18 @@
5054

5155
incluster_config.configure(actual)
5256
expect(actual).to be_same_configuration_as(expected)
57+
58+
old_expired_at = incluster_config.token_expires_at
59+
incluster_config.instance_variable_set(
60+
:@token_file,
61+
Kubernetes::Testing.file_fixture('tokens/token2').to_s
62+
)
63+
allow(Time).to receive(:now).and_return(Time.now+5)
64+
actual.api_key_with_prefix('authorization')
65+
66+
expected.api_key['authorization'] = 'Bearer token2'
67+
expect(actual).to be_same_configuration_as(expected)
68+
expect(incluster_config.token_expires_at).to be > old_expired_at
5369
end
5470
end
5571

@@ -141,4 +157,4 @@
141157
end
142158
end
143159
end
144-
# rubocop:enable BlockLength
160+
# rubocop:enable Metrics/BlockLength
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
token2

kubernetes/src/kubernetes/config/incluster_config.rb

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
#
1415

1516
require 'kubernetes/configuration'
1617
require 'kubernetes/config/error'
@@ -19,27 +20,29 @@ module Kubernetes
1920
# The InClusterConfig class represents configuration for authn/authz in a
2021
# Kubernetes cluster.
2122
class InClusterConfig
22-
# rubocop:disable LineLength
23+
# rubocop:disable Metrics/LineLength
2324
SERVICE_HOST_ENV_NAME = 'KUBERNETES_SERVICE_HOST'.freeze
2425
SERVICE_PORT_ENV_NAME = 'KUBERNETES_SERVICE_PORT'.freeze
2526
SERVICE_TOKEN_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/token'.freeze
2627
SERVICE_CA_CERT_FILENAME = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'.freeze
27-
# rubocop:enable LineLength
28+
TOKEN_REFRESH_PERIOD = 60 # 1 minute
29+
# rubocop:enable Metrics/LineLength
2830

2931
attr_accessor :host
3032
attr_accessor :port
3133
attr_accessor :token
34+
attr_accessor :token_expires_at
3235

3336
def validate
3437
unless (self.host = env[SERVICE_HOST_ENV_NAME]) &&
3538
(self.port = env[SERVICE_PORT_ENV_NAME])
3639
raise ConfigError, 'Service host/port is not set'
3740
end
3841

39-
# rubocop:disable LineLength
42+
# rubocop:disable Metrics/LineLength
4043
raise ConfigError, 'Service token file does not exists' unless File.file?(token_file)
4144
raise ConfigError, 'Service token file does not exists' unless File.file?(ca_cert)
42-
# rubocop:enable LineLength
45+
# rubocop:enable Metrics/LineLength
4346
end
4447

4548
def self.in_cluster?
@@ -62,19 +65,42 @@ def token_file
6265
@token_file
6366
end
6467

68+
def token_refresh_period
69+
@token_refresh_period ||= TOKEN_REFRESH_PERIOD
70+
@token_refresh_period
71+
end
72+
6573
def load_token
6674
File.open(token_file) do |io|
6775
self.token = io.read.chomp
76+
self.token_expires_at = Time.now + token_refresh_period
6877
end
6978
end
7079

71-
def configure(configuration)
80+
# rubocop:disable Metrics/AbcSize
81+
def configure(configuration, try_refresh_token: true)
7282
validate
7383
load_token
7484
configuration.api_key['authorization'] = "Bearer #{token}"
7585
configuration.scheme = 'https'
7686
configuration.host = "#{host}:#{port}"
7787
configuration.ssl_ca_cert = ca_cert
88+
return unless try_refresh_token
89+
90+
Configuration.instance_variable_set(:@in_cluster_config, self)
91+
Configuration.prepend(Module.new do
92+
# rubocop:disable Metrics/LineLength
93+
def api_key_with_prefix(identifier)
94+
in_cluster_config = self.class.instance_variable_get(:@in_cluster_config)
95+
if identifier == 'authorization' && @api_key.key?(identifier) && in_cluster_config.token_expires_at <= Time.now
96+
in_cluster_config.load_token
97+
@api_key[identifier] = 'Bearer ' + in_cluster_config.token
98+
end
99+
super identifier
100+
end
101+
# rubocop:enable Metrics/LineLength
102+
end)
78103
end
104+
# rubocop:enable Metrics/AbcSize
79105
end
80106
end

0 commit comments

Comments
 (0)