cabal-api 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/cabal-api.gemspec +6 -1
- data/lib/cabal/api/base.rb +2 -0
- data/lib/cabal/api/cluster.rb +39 -0
- data/lib/cabal/api/common/authenticated.rb +30 -0
- data/lib/cabal/api/common/mistakes.rb +21 -0
- data/lib/cabal/api/common/public_key.rb +26 -0
- data/lib/cabal/api/common.rb +1 -0
- data/lib/cabal/api/user.rb +49 -0
- data/lib/cabal/api/v1/base.rb +0 -1
- data/lib/cabal/api/v1/public_key.rb +2 -12
- data/lib/cabal/api/v2/base.rb +16 -0
- data/lib/cabal/api/v2/private_key.rb +46 -0
- data/lib/cabal/api/v2/public_key.rb +13 -0
- data/lib/cabal/api/version.rb +1 -1
- data/lib/cabal/api.rb +6 -2
- metadata +89 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 633175e3c38cc1c65baddaedcd27f2759e89a1af
|
4
|
+
data.tar.gz: b547ecf19c5443809c21be14cc22fe1466055962
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5d78bb2f96f4d25a08d85edbb72cb376ddfb008d838364d61c4ed2be0a0c9859876072ddfc06f58888df3b9cacb355af26a2cd9bd7e53788123ecbc79d6ec4c
|
7
|
+
data.tar.gz: a3c43b4d082fb850033607e999467e214cdc557641145ac41b356606bbae08843c5e5cec6939dca697ab9c02b4af63b9d2a502d538482cbe1aeaefe2268b60f0
|
data/cabal-api.gemspec
CHANGED
@@ -24,8 +24,13 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_development_dependency "rack-test", '~> 0.6'
|
25
25
|
spec.add_development_dependency "rspec", '~> 3.3'
|
26
26
|
spec.add_development_dependency "factis", '~> 1.0'
|
27
|
-
spec.add_development_dependency "fakeredis", '~> 0.5'
|
28
27
|
spec.add_development_dependency "simplecov", '~> 0.10'
|
28
|
+
spec.add_development_dependency "redis"
|
29
|
+
spec.add_development_dependency "database_cleaner"
|
29
30
|
spec.add_runtime_dependency "cabal", '~> 0.2'
|
30
31
|
spec.add_runtime_dependency "grape", '~> 0.13'
|
32
|
+
spec.add_runtime_dependency "ohm"
|
33
|
+
spec.add_runtime_dependency "ohm-contrib"
|
34
|
+
spec.add_runtime_dependency "bcrypt"
|
35
|
+
spec.add_runtime_dependency "sshkey"
|
31
36
|
end
|
data/lib/cabal/api/base.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'ohm'
|
2
|
+
require 'ohm/contrib'
|
3
|
+
require 'sshkey'
|
4
|
+
require 'cabal/util'
|
5
|
+
|
6
|
+
module Cabal
|
7
|
+
module API
|
8
|
+
class Cluster < Ohm::Model
|
9
|
+
include Ohm::Callbacks
|
10
|
+
|
11
|
+
# The secret key should not be saved plain, but we want to access it
|
12
|
+
# immediately after creation
|
13
|
+
attr_accessor :secret_key
|
14
|
+
|
15
|
+
attribute :name
|
16
|
+
attribute :private_key
|
17
|
+
attribute :public_key
|
18
|
+
|
19
|
+
# Enable lookups via cluster name
|
20
|
+
index :name
|
21
|
+
|
22
|
+
# Ensure that cluster name is unique
|
23
|
+
unique :name
|
24
|
+
|
25
|
+
def before_create
|
26
|
+
self.name = Cabal::Util.normalize(name)
|
27
|
+
|
28
|
+
sshkey = SSHKey.generate(type: 'RSA', bits: 2048, comment: "#{name}-cabal")
|
29
|
+
self.private_key = sshkey.private_key
|
30
|
+
self.public_key = sshkey.ssh_public_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.by_cluster_name(name)
|
34
|
+
name = Cabal::Util.normalize(name)
|
35
|
+
find(name: name).first || create(name: name)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'cabal/api/user'
|
2
|
+
|
3
|
+
module Cabal
|
4
|
+
module API
|
5
|
+
module Common
|
6
|
+
module Authenticated
|
7
|
+
def self.included(base)
|
8
|
+
base.class_eval do
|
9
|
+
helpers do
|
10
|
+
def current_user
|
11
|
+
authorization = headers['Authorization'].to_s
|
12
|
+
access_key, signature = authorization.split(':')
|
13
|
+
user = Cabal::API::User.find(access_key: access_key).first
|
14
|
+
if user && user.authenticated_with?(signature)
|
15
|
+
user
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def authenticate!
|
22
|
+
error!({message: 'Unauthorized.'}, 401) unless current_user
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Cabal
|
2
|
+
module API
|
3
|
+
module Common
|
4
|
+
module Mistakes
|
5
|
+
def self.included(base)
|
6
|
+
base.class_eval do
|
7
|
+
error_formatter :txt, ->(message, backtrace, options, env) {
|
8
|
+
message[:message]
|
9
|
+
}
|
10
|
+
|
11
|
+
helpers do
|
12
|
+
def messagify(message)
|
13
|
+
{message: message}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'cabal/util'
|
2
|
+
require 'cabal/api/cluster'
|
3
|
+
|
4
|
+
module Cabal
|
5
|
+
module API
|
6
|
+
module Common
|
7
|
+
module PublicKey
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
formatter :txt, ->(object, env) {
|
11
|
+
object[:public_ssh_key]
|
12
|
+
}
|
13
|
+
|
14
|
+
get '/key/:name' do
|
15
|
+
cluster = Cabal::API::Cluster.by_cluster_name(params[:name])
|
16
|
+
{
|
17
|
+
name: cluster.name,
|
18
|
+
public_ssh_key: cluster.public_key
|
19
|
+
}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'cabal/api/common/public_key'
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'ohm'
|
2
|
+
require 'ohm/contrib'
|
3
|
+
require 'bcrypt'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Cabal
|
7
|
+
module API
|
8
|
+
class User < Ohm::Model
|
9
|
+
include Ohm::Callbacks
|
10
|
+
|
11
|
+
# The secret key should not be saved plain, but we want to access it
|
12
|
+
# immediately after creation
|
13
|
+
attr_accessor :secret_key
|
14
|
+
|
15
|
+
attribute :email
|
16
|
+
attribute :access_key
|
17
|
+
attribute :crypted_secret_key
|
18
|
+
|
19
|
+
# Enable lookups via either the user's email or their access key.
|
20
|
+
index :email
|
21
|
+
index :access_key
|
22
|
+
|
23
|
+
# Ensure that email and access keys are unique
|
24
|
+
unique :email
|
25
|
+
unique :access_key
|
26
|
+
|
27
|
+
def before_create
|
28
|
+
set_access_key
|
29
|
+
set_secret_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def authenticated_with?(secret_key)
|
33
|
+
return false unless crypted_secret_key
|
34
|
+
|
35
|
+
BCrypt::Password.new(crypted_secret_key) == secret_key
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
def set_access_key
|
40
|
+
self.access_key = SecureRandom.hex(16)
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_secret_key
|
44
|
+
self.secret_key = SecureRandom.hex(32)
|
45
|
+
self.crypted_secret_key = BCrypt::Password.create(secret_key)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/cabal/api/v1/base.rb
CHANGED
@@ -1,22 +1,12 @@
|
|
1
1
|
require 'grape'
|
2
|
-
require 'cabal/cluster'
|
3
2
|
require 'cabal/util'
|
3
|
+
require 'cabal/api/common'
|
4
4
|
|
5
5
|
module Cabal
|
6
6
|
module API
|
7
7
|
module V1
|
8
8
|
class PublicKey < Grape::API
|
9
|
-
|
10
|
-
object[:public_ssh_key]
|
11
|
-
}
|
12
|
-
|
13
|
-
get '/key/:name' do
|
14
|
-
name = Cabal::Util.normalize(params[:name])
|
15
|
-
{
|
16
|
-
name: name,
|
17
|
-
public_ssh_key: Cabal::Cluster.new(name).public_ssh_key
|
18
|
-
}
|
19
|
-
end
|
9
|
+
include Cabal::API::Common::PublicKey
|
20
10
|
end
|
21
11
|
end
|
22
12
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'grape'
|
2
|
+
require 'cabal/api/v2/public_key'
|
3
|
+
require 'cabal/api/v2/private_key'
|
4
|
+
|
5
|
+
module Cabal
|
6
|
+
module API
|
7
|
+
module V2
|
8
|
+
class Base < Grape::API
|
9
|
+
version 'v2', using: :path
|
10
|
+
|
11
|
+
mount Cabal::API::V2::PublicKey
|
12
|
+
mount Cabal::API::V2::PrivateKey
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'grape'
|
2
|
+
require 'cabal/util'
|
3
|
+
require 'cabal/api/cluster'
|
4
|
+
require 'cabal/api/user'
|
5
|
+
require 'cabal/api/common/authenticated'
|
6
|
+
require 'cabal/api/common/mistakes'
|
7
|
+
|
8
|
+
module Cabal
|
9
|
+
module API
|
10
|
+
module V2
|
11
|
+
class PrivateKey < Grape::API
|
12
|
+
include Cabal::API::Common::Authenticated
|
13
|
+
include Cabal::API::Common::Mistakes
|
14
|
+
|
15
|
+
formatter :txt, ->(object, env) {
|
16
|
+
object[:private_ssh_key]
|
17
|
+
}
|
18
|
+
|
19
|
+
helpers do
|
20
|
+
def error_if_not_found!(cluster, name)
|
21
|
+
unless cluster
|
22
|
+
error!(
|
23
|
+
messagify("The cluster '#{name}' could not be found."),
|
24
|
+
404
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
get '/private-key/:name' do
|
31
|
+
authenticate!
|
32
|
+
|
33
|
+
cluster_name = Cabal::Util.normalize(params[:name])
|
34
|
+
cluster = Cabal::API::Cluster.find(name: cluster_name).first
|
35
|
+
|
36
|
+
error_if_not_found!(cluster, cluster_name)
|
37
|
+
|
38
|
+
{
|
39
|
+
name: cluster.name,
|
40
|
+
private_ssh_key: cluster.private_key
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/cabal/api/version.rb
CHANGED
data/lib/cabal/api.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'ohm'
|
2
|
+
require 'cabal/api/version'
|
3
|
+
require 'cabal/api/base'
|
4
|
+
require 'cabal/api/cluster'
|
5
|
+
require 'cabal/api/user'
|
3
6
|
|
4
7
|
module Cabal
|
5
8
|
module Api
|
9
|
+
Ohm.redis = Redic.new(ENV['REDIS_URL'] || 'redis://localhost:6379')
|
6
10
|
end
|
7
11
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cabal-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dennis Walters
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -95,33 +95,47 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.10'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.10'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: redis
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - ">="
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: database_cleaner
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: cabal
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +164,62 @@ dependencies:
|
|
150
164
|
- - "~>"
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0.13'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: ohm
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: ohm-contrib
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :runtime
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: bcrypt
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :runtime
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: sshkey
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '0'
|
216
|
+
type: :runtime
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '0'
|
153
223
|
description:
|
154
224
|
email:
|
155
225
|
- dwalters@engineyard.com
|
@@ -172,8 +242,17 @@ files:
|
|
172
242
|
- config/cucumber.yml
|
173
243
|
- lib/cabal/api.rb
|
174
244
|
- lib/cabal/api/base.rb
|
245
|
+
- lib/cabal/api/cluster.rb
|
246
|
+
- lib/cabal/api/common.rb
|
247
|
+
- lib/cabal/api/common/authenticated.rb
|
248
|
+
- lib/cabal/api/common/mistakes.rb
|
249
|
+
- lib/cabal/api/common/public_key.rb
|
250
|
+
- lib/cabal/api/user.rb
|
175
251
|
- lib/cabal/api/v1/base.rb
|
176
252
|
- lib/cabal/api/v1/public_key.rb
|
253
|
+
- lib/cabal/api/v2/base.rb
|
254
|
+
- lib/cabal/api/v2/private_key.rb
|
255
|
+
- lib/cabal/api/v2/public_key.rb
|
177
256
|
- lib/cabal/api/version.rb
|
178
257
|
homepage: http://github.com/ess/cabal-api
|
179
258
|
licenses:
|