Class: OpenNebula::X509Auth

Inherits:
Object
  • Object
show all
Defined in:
lib/opennebula/x509_auth.rb

Overview

X509 authentication class. It can be used as a driver for auth_mad as auth method is defined. It also holds some helper methods to be used by oneauth command

Direct Known Subclasses

ServerX509Auth

Constant Summary collapse

ETC_LOCATION =
ENV["ONE_LOCATION"] + "/etc"
LOGIN_PATH =
ENV['HOME']+'/.one/one_x509'
X509_AUTH_CONF_PATH =
ETC_LOCATION + "/auth/x509_auth.conf"
X509_DEFAULTS =
{
    :ca_dir   => ETC_LOCATION + "/auth/certificates"
}

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ X509Auth

Initialize x509Auth object

Parameters:

  • default (Hash)

    options for path

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

    a customizable set of options

Options Hash (options):

  • :certs_pem (String)

    cert chain array in colon-separated pem format

  • :key_pem (String)

    key in pem format

  • :ca_dir (String)

    directory of trusted CA’s. Needed for auth method, not for login.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/opennebula/x509_auth.rb', line 63

def initialize(options={})
    @options ||= X509_DEFAULTS
    @options.merge!(options)

    load_options(X509_AUTH_CONF_PATH)

    @cert_chain = @options[:certs_pem].collect do |cert_pem|
        OpenSSL::X509::Certificate.new(cert_pem)
    end

    if @options[:key_pem]
        @key  = OpenSSL::PKey::RSA.new(@options[:key_pem])
    end
end

Class Method Details

.escape_dn(dn) ⇒ Object



45
46
47
# File 'lib/opennebula/x509_auth.rb', line 45

def self.escape_dn(dn)
    dn.gsub(/\s/) { |s| "\\"+s[0].ord.to_s(16) }
end

.unescape_dn(dn) ⇒ Object



49
50
51
# File 'lib/opennebula/x509_auth.rb', line 49

def self.unescape_dn(dn)
    dn.gsub(/\\[0-9a-f]{2}/) { |s| s[1,2].to_i(16).chr }
end

Instance Method Details

#authenticate(user, pass, signed_text) ⇒ Object

Server side

auth method for auth_mad



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/opennebula/x509_auth.rb', line 123

def authenticate(user, pass, signed_text)
    begin
        # Decryption demonstrates that the user posessed the private key.
        _user, expires = decrypt(signed_text).split(':')

        return "User name missmatch" if user != _user

        return "x509 proxy expired"  if Time.now.to_i >= expires.to_i

        # Some DN in the chain must match a DN in the password
        dn_ok = @cert_chain.each do |cert|
            if pass.split('|').include?(
                    self.class.escape_dn(cert.subject.to_s))
                break true
            end
        end

        unless dn_ok == true
            return "Certificate subject missmatch"
        end

        validate

        return true
    rescue => e
        return e.message
    end
end

#login(user, expire = 0) ⇒ Object

Creates the login file for x509 authentication at ~/.one/one_x509. By default it is valid as long as the certificate is valid. It can be changed to any number of seconds with expire parameter (sec.)



85
86
87
# File 'lib/opennebula/x509_auth.rb', line 85

def (user, expire=0)
    ((user,expire))
end

#login_token(user, expire) ⇒ Object

Generates a login token in the form: user_name:x509:user_name:time_expires:cert_chain

- user_name:time_expires is encrypted with the user certificate
- user_name:time_expires:cert_chain is base64 encoded


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/opennebula/x509_auth.rb', line 99

def (user, expire)
    if expire != 0
        expires = Time.now.to_i + expire.to_i
    else
        expires = @cert_chain[0].not_after.to_i
    end

    text_to_sign = "#{user}:#{expires}"
    signed_text  = encrypt(text_to_sign)

    certs_pem = @cert_chain.collect{|cert| cert.to_pem}.join(":")

    token     = "#{signed_text}:#{certs_pem}"
    token64   = Base64::encode64(token).strip.delete("\n")

     = "#{user}:#{token64}"

    
end

#passwordObject

Returns a valid password string to create a user using this auth driver. In this case the dn of the user certificate.



91
92
93
# File 'lib/opennebula/x509_auth.rb', line 91

def password
    self.class.escape_dn(@cert_chain[0].subject.to_s)
end