Module: Sensu::Plugins::Kubernetes::Client

Included in:
CLI
Defined in:
lib/sensu-plugins-kubernetes/client.rb

Overview

A mixin module that provides Kubernetes client (kubeclient) support.

Constant Summary collapse

INCLUSTER_CA_FILE =

The location of the service account provided CA. (if the cluster is configured to provide it)

'/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'.freeze
INCLUSTER_TOKEN_FILE =

The location of the service account provided authentication token.

'/var/run/secrets/kubernetes.io/serviceaccount/token'.freeze

Instance Method Summary collapse

Instance Method Details

#kubeclient(options = {}) ⇒ Object

Creates a new Kubeclient::Client instance using the given SSL and authentication options (if any)

Parameters:

  • options (Hash) (defaults to: {})

    The Kubernetes API connection details.

Options Hash (options):

  • :server (String)

    URL to API server

  • :version (String)

    API version

  • :incluster (Boolean)

    Use service account authentication if true

  • :ca_file (String)

    CA file used to verify API server certificate

  • :client_cert_file (String)

    Client certificate file to present

  • :client_key_file (String)

    Client private key file for the client certificate

  • :username (String)

    Username with access to API

  • :password (String)

    If a username is passed, also pass a password

  • :token (String)

    The bearer token for Kubernetes authorization

  • :token_file (String)

    A file containing the bearer token for Kubernetes authorization

Raises:

  • (ArgumentError)

    If an invalid option, or combination of options, is given.

  • (Errono::*)

    If there is a problem reading the client certificate or private key file.

  • (OpenSSL::X509::CertificateError)

    If there is a problem with the client certificate.

  • (OpenSSL::PKey::RSAError)

    If there is a problem with the client private key.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/sensu-plugins-kubernetes/client.rb', line 46

def kubeclient(options = {})
  raise(ArgumentError, 'options must be a hash') unless options.is_a?(Hash)

  api_server = options[:server]
  api_version = options[:version]

  ssl_options = {
    ca_file: options[:ca_file]
  }
  auth_options = {
    username: options[:username],
    password: options[:password],
    bearer_token: options[:token],
    bearer_token_file: options[:token_file]
  }

  if [:client_cert_file, :client_key_file].count { |k| options[k] } == 1
    raise ArgumentError, 'SSL requires both client cert and client key'
  end

  if options[:client_cert_file]
    begin
      ssl_options[:client_cert] = OpenSSL::X509::Certificate.new(File.read(options[:client_cert_file]))
    rescue => e
      raise e, "Unable to read client certificate: #{e}", e.backtrace
    end
  end

  if options[:client_key_file]
    begin
      ssl_options[:client_key] = OpenSSL::PKey::RSA.new(File.read(options[:client_key_file]))
    rescue => e
      raise e, "Unable to read client key: #{e}", e.backtrace
    end
  end

  if options[:incluster]
    # Provide in-cluster defaults, if not already specified
    # (following the kubernetes incluster config code, more or less)

    # api-server
    # TODO: use in-cluster DNS ??
    if api_server.nil?
      host = ENV['KUBERNETES_SERVICE_HOST']
      port = ENV['KUBERNETES_SERVICE_PORT']
      if host.nil? || port.nil?
        raise ArgumentError, 'unable to load in-cluster configuration,'\
             ' KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT'\
             ' must be defined'
      end
      api_server = URI::HTTPS.build(host: host, port: port, path: '/api')
    end

    # ca file, but only if it exists
    if ssl_options[:ca_file].nil? && File.exist?(INCLUSTER_CA_FILE)
      # Readability/permission issues should be left to kubeclient
      ssl_options[:ca_file] = INCLUSTER_CA_FILE
    end

    # token file
    if auth_options[:bearer_token_file].nil?
      auth_options[:bearer_token_file] = INCLUSTER_TOKEN_FILE
    end
  end

  ssl_options[:verify_ssl] = ssl_options[:ca_file] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE

  begin
    # new only throws errors on bad arguments
    Kubeclient::Client.new(api_server, api_version,
                           ssl_options: ssl_options,
                           auth_options: auth_options)
  rescue URI::InvalidURIError => e
    # except for this one, which we'll re-wrap to make catching easier
    raise ArgumentError, "Invalid API server: #{e}", e.backtrace
  end
end