slosilo 0.0.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +0 -2
- data/LICENSE +2 -2
- data/README.md +8 -128
- data/lib/slosilo/adapters/abstract_adapter.rb +0 -4
- data/lib/slosilo/adapters/mock_adapter.rb +1 -14
- data/lib/slosilo/adapters/sequel_adapter/migration.rb +2 -5
- data/lib/slosilo/adapters/sequel_adapter.rb +5 -67
- data/lib/slosilo/attr_encrypted.rb +7 -33
- data/lib/slosilo/http_request.rb +59 -0
- data/lib/slosilo/key.rb +6 -129
- data/lib/slosilo/keystore.rb +12 -40
- data/lib/slosilo/rack/middleware.rb +123 -0
- data/lib/slosilo/symmetric.rb +17 -47
- data/lib/slosilo/version.rb +2 -21
- data/lib/slosilo.rb +2 -2
- data/lib/tasks/slosilo.rake +0 -10
- data/slosilo.gemspec +6 -19
- data/spec/http_request_spec.rb +107 -0
- data/spec/http_stack_spec.rb +44 -0
- data/spec/key_spec.rb +32 -175
- data/spec/keystore_spec.rb +2 -15
- data/spec/rack_middleware_spec.rb +109 -0
- data/spec/random_spec.rb +2 -12
- data/spec/sequel_adapter_spec.rb +22 -133
- data/spec/slosilo_spec.rb +12 -78
- data/spec/spec_helper.rb +15 -37
- data/spec/symmetric_spec.rb +26 -69
- metadata +51 -104
- checksums.yaml +0 -7
- data/.github/CODEOWNERS +0 -10
- data/.gitleaks.toml +0 -221
- data/.kateproject +0 -4
- data/CHANGELOG.md +0 -50
- data/CONTRIBUTING.md +0 -16
- data/Jenkinsfile +0 -132
- data/SECURITY.md +0 -42
- data/dev/Dockerfile.dev +0 -7
- data/dev/docker-compose.yml +0 -8
- data/lib/slosilo/adapters/file_adapter.rb +0 -42
- data/lib/slosilo/adapters/memory_adapter.rb +0 -31
- data/lib/slosilo/errors.rb +0 -15
- data/lib/slosilo/jwt.rb +0 -122
- data/publish.sh +0 -5
- data/secrets.yml +0 -1
- data/spec/encrypted_attributes_spec.rb +0 -114
- data/spec/file_adapter_spec.rb +0 -81
- data/spec/jwt_spec.rb +0 -102
- data/test.sh +0 -8
data/lib/slosilo/jwt.rb
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
|
-
module Slosilo
|
4
|
-
# A JWT-formatted Slosilo token.
|
5
|
-
# @note This is not intended to be a general-purpose JWT implementation.
|
6
|
-
class JWT
|
7
|
-
# Create a new unsigned token with the given claims.
|
8
|
-
# @param claims [#to_h] claims to embed in this token.
|
9
|
-
def initialize claims = {}
|
10
|
-
@claims = JSONHash[claims]
|
11
|
-
end
|
12
|
-
|
13
|
-
# Parse a token in compact representation
|
14
|
-
def self.parse_compact raw
|
15
|
-
load *raw.split('.', 3).map(&Base64.method(:urlsafe_decode64))
|
16
|
-
end
|
17
|
-
|
18
|
-
# Parse a token in JSON representation.
|
19
|
-
# @note only single signature is currently supported.
|
20
|
-
def self.parse_json raw
|
21
|
-
raw = JSON.load raw unless raw.respond_to? :to_h
|
22
|
-
parts = raw.to_h.values_at(*%w(protected payload signature))
|
23
|
-
fail ArgumentError, "input not a complete JWT" unless parts.all?
|
24
|
-
load *parts.map(&Base64.method(:urlsafe_decode64))
|
25
|
-
end
|
26
|
-
|
27
|
-
# Add a signature.
|
28
|
-
# @note currently only a single signature is handled;
|
29
|
-
# the token will be frozen after this operation.
|
30
|
-
def add_signature header, &sign
|
31
|
-
@claims = canonicalize_claims.freeze
|
32
|
-
@header = JSONHash[header].freeze
|
33
|
-
@signature = sign[string_to_sign].freeze
|
34
|
-
freeze
|
35
|
-
end
|
36
|
-
|
37
|
-
def string_to_sign
|
38
|
-
[header, claims].map(&method(:encode)).join '.'
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns the JSON serialization of this JWT.
|
42
|
-
def to_json *a
|
43
|
-
{
|
44
|
-
protected: encode(header),
|
45
|
-
payload: encode(claims),
|
46
|
-
signature: encode(signature)
|
47
|
-
}.to_json *a
|
48
|
-
end
|
49
|
-
|
50
|
-
# Returns the compact serialization of this JWT.
|
51
|
-
def to_s
|
52
|
-
[header, claims, signature].map(&method(:encode)).join('.')
|
53
|
-
end
|
54
|
-
|
55
|
-
attr_accessor :claims, :header, :signature
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
# Create a JWT token object from existing header, payload, and signature strings.
|
60
|
-
# @param header [#to_s] URLbase64-encoded representation of the protected header
|
61
|
-
# @param payload [#to_s] URLbase64-encoded representation of the token payload
|
62
|
-
# @param signature [#to_s] URLbase64-encoded representation of the signature
|
63
|
-
def self.load header, payload, signature
|
64
|
-
self.new(JSONHash.load payload).tap do |token|
|
65
|
-
token.header = JSONHash.load header
|
66
|
-
token.signature = signature.to_s.freeze
|
67
|
-
token.freeze
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def canonicalize_claims
|
72
|
-
claims[:iat] = Time.now unless claims.include? :iat
|
73
|
-
claims[:iat] = claims[:iat].to_time.to_i
|
74
|
-
claims[:exp] = claims[:exp].to_time.to_i if claims.include? :exp
|
75
|
-
JSONHash[claims.to_a]
|
76
|
-
end
|
77
|
-
|
78
|
-
# Convenience method to make the above code clearer.
|
79
|
-
# Converts to string and urlbase64-encodes.
|
80
|
-
def encode s
|
81
|
-
Base64.urlsafe_encode64 s.to_s
|
82
|
-
end
|
83
|
-
|
84
|
-
# a hash with a possibly frozen JSON stringification
|
85
|
-
class JSONHash < Hash
|
86
|
-
def to_s
|
87
|
-
@repr || to_json
|
88
|
-
end
|
89
|
-
|
90
|
-
def freeze
|
91
|
-
@repr = to_json.freeze
|
92
|
-
super
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.load raw
|
96
|
-
self[JSON.load raw.to_s].tap do |h|
|
97
|
-
h.send :repr=, raw
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
private
|
102
|
-
|
103
|
-
def repr= raw
|
104
|
-
@repr = raw.freeze
|
105
|
-
freeze
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Try to convert by detecting token representation and parsing
|
111
|
-
def self.JWT raw
|
112
|
-
if raw.is_a? JWT
|
113
|
-
raw
|
114
|
-
elsif raw.respond_to?(:to_h) || raw =~ /\A\s*\{/
|
115
|
-
JWT.parse_json raw
|
116
|
-
else
|
117
|
-
JWT.parse_compact raw
|
118
|
-
end
|
119
|
-
rescue
|
120
|
-
raise ArgumentError, "invalid value for JWT(): #{raw.inspect}"
|
121
|
-
end
|
122
|
-
end
|
data/publish.sh
DELETED
data/secrets.yml
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
RUBYGEMS_API_KEY: !var rubygems/api-key
|
@@ -1,114 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'slosilo/attr_encrypted'
|
3
|
-
|
4
|
-
describe Slosilo::EncryptedAttributes do
|
5
|
-
before(:all) do
|
6
|
-
Slosilo::encryption_key = OpenSSL::Cipher.new("aes-256-gcm").random_key
|
7
|
-
end
|
8
|
-
|
9
|
-
let(:aad) { proc{ |_| "hithere" } }
|
10
|
-
|
11
|
-
let(:base){
|
12
|
-
Class.new do
|
13
|
-
attr_accessor :normal_ivar,:with_aad
|
14
|
-
def stupid_ivar
|
15
|
-
side_effect!
|
16
|
-
@_explicit
|
17
|
-
end
|
18
|
-
def stupid_ivar= e
|
19
|
-
side_effect!
|
20
|
-
@_explicit = e
|
21
|
-
end
|
22
|
-
def side_effect!
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
-
}
|
27
|
-
|
28
|
-
let(:sub){
|
29
|
-
Class.new(base) do
|
30
|
-
attr_encrypted :normal_ivar, :stupid_ivar
|
31
|
-
end
|
32
|
-
}
|
33
|
-
|
34
|
-
subject{ sub.new }
|
35
|
-
|
36
|
-
context "when setting a normal ivar" do
|
37
|
-
let(:value){ "some value" }
|
38
|
-
it "stores an encrypted value in the ivar" do
|
39
|
-
subject.normal_ivar = value
|
40
|
-
expect(subject.instance_variable_get(:"@normal_ivar")).to_not eq(value)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "recovers the value set" do
|
44
|
-
subject.normal_ivar = value
|
45
|
-
expect(subject.normal_ivar).to eq(value)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context "when setting an attribute with an implementation" do
|
50
|
-
it "calls the base class method" do
|
51
|
-
expect(subject).to receive_messages(:side_effect! => nil)
|
52
|
-
subject.stupid_ivar = "hi"
|
53
|
-
expect(subject.stupid_ivar).to eq("hi")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context "when given an :aad option" do
|
58
|
-
|
59
|
-
let(:cipher){ Slosilo::EncryptedAttributes.cipher }
|
60
|
-
let(:key){ Slosilo::EncryptedAttributes.key}
|
61
|
-
context "that is a string" do
|
62
|
-
let(:aad){ "hello there" }
|
63
|
-
before{ sub.attr_encrypted :with_aad, aad: aad }
|
64
|
-
it "encrypts the value with the given string for auth data" do
|
65
|
-
expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad)
|
66
|
-
subject.with_aad = "hello"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "decrypts the encrypted value" do
|
70
|
-
subject.with_aad = "foo"
|
71
|
-
expect(subject.with_aad).to eq("foo")
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context "that is nil" do
|
76
|
-
let(:aad){ nil }
|
77
|
-
before{ sub.attr_encrypted :with_aad, aad: aad }
|
78
|
-
it "encrypts the value with an empty string for auth data" do
|
79
|
-
expect(cipher).to receive(:encrypt).with("hello",key: key, aad: "").and_call_original
|
80
|
-
subject.with_aad = "hello"
|
81
|
-
end
|
82
|
-
|
83
|
-
it "decrypts the encrypted value" do
|
84
|
-
subject.with_aad = "hello"
|
85
|
-
expect(subject.with_aad).to eq("hello")
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "that is a proc" do
|
90
|
-
let(:aad){
|
91
|
-
proc{ |o| "x" }
|
92
|
-
}
|
93
|
-
|
94
|
-
before{ sub.attr_encrypted :with_aad, aad: aad }
|
95
|
-
|
96
|
-
it "calls the proc with the object being encrypted" do
|
97
|
-
expect(aad).to receive(:[]).with(subject).and_call_original
|
98
|
-
subject.with_aad = "hi"
|
99
|
-
end
|
100
|
-
|
101
|
-
it "encrypts the value with the string returned for auth data" do
|
102
|
-
expect(cipher).to receive(:encrypt).with("hello", key: key, aad: aad[subject]).and_call_original
|
103
|
-
subject.with_aad = "hello"
|
104
|
-
end
|
105
|
-
it "decrypts the encrypted value" do
|
106
|
-
subject.with_aad = "hello"
|
107
|
-
expect(subject.with_aad).to eq("hello")
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
|
114
|
-
end
|
data/spec/file_adapter_spec.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
|
-
require 'slosilo/adapters/file_adapter'
|
5
|
-
|
6
|
-
describe Slosilo::Adapters::FileAdapter do
|
7
|
-
include_context "with example key"
|
8
|
-
|
9
|
-
let(:dir) { Dir.mktmpdir }
|
10
|
-
let(:adapter) { Slosilo::Adapters::FileAdapter.new dir }
|
11
|
-
subject { adapter }
|
12
|
-
|
13
|
-
describe "#get_key" do
|
14
|
-
context "when given key does not exist" do
|
15
|
-
it "returns nil" do
|
16
|
-
expect(subject.get_key(:whatever)).not_to be
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "#put_key" do
|
22
|
-
context "unacceptable id" do
|
23
|
-
let(:id) { "foo.bar" }
|
24
|
-
it "isn't accepted" do
|
25
|
-
expect { subject.put_key id, key }.to raise_error /id should not contain a period/
|
26
|
-
end
|
27
|
-
end
|
28
|
-
context "acceptable id" do
|
29
|
-
let(:id) { "id" }
|
30
|
-
let(:key_encrypted) { "encrypted key" }
|
31
|
-
let(:fname) { "#{dir}/#{id}.key" }
|
32
|
-
it "creates the key" do
|
33
|
-
expect(Slosilo::EncryptedAttributes).to receive(:encrypt).with(key.to_der).and_return key_encrypted
|
34
|
-
expect(File).to receive(:write).with(fname, key_encrypted)
|
35
|
-
expect(File).to receive(:chmod).with(0400, fname)
|
36
|
-
subject.put_key id, key
|
37
|
-
expect(subject.instance_variable_get("@keys")[id]).to eq(key)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "#each" do
|
43
|
-
before { adapter.instance_variable_set("@keys", one: :onek, two: :twok) }
|
44
|
-
|
45
|
-
it "iterates over each key" do
|
46
|
-
results = []
|
47
|
-
adapter.each { |id,k| results << { id => k } }
|
48
|
-
expect(results).to eq([ { one: :onek}, {two: :twok } ])
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context 'with real key store' do
|
53
|
-
let(:id) { 'some id' }
|
54
|
-
|
55
|
-
before do
|
56
|
-
Slosilo::encryption_key = Slosilo::Symmetric.new.random_key
|
57
|
-
pre_adapter = Slosilo::Adapters::FileAdapter.new dir
|
58
|
-
pre_adapter.put_key(id, key)
|
59
|
-
end
|
60
|
-
|
61
|
-
describe '#get_key' do
|
62
|
-
it "loads and decrypts the key" do
|
63
|
-
expect(adapter.get_key(id)).to eq(key)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe '#get_by_fingerprint' do
|
68
|
-
it "can look up a key by a fingerprint" do
|
69
|
-
expect(adapter.get_by_fingerprint(key_fingerprint)).to eq([key, id])
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe '#each' do
|
74
|
-
it "enumerates the keys" do
|
75
|
-
results = []
|
76
|
-
adapter.each { |id,k| results << { id => k } }
|
77
|
-
expect(results).to eq([ { id => key } ])
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
data/spec/jwt_spec.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
# (Mostly) integration tests for JWT token format
|
4
|
-
describe Slosilo::Key do
|
5
|
-
include_context "with example key"
|
6
|
-
|
7
|
-
describe '#issue_jwt' do
|
8
|
-
it 'issues an JWT token with given claims' do
|
9
|
-
allow(Time).to receive(:now) { DateTime.parse('2014-06-04 23:22:32 -0400').to_time }
|
10
|
-
|
11
|
-
tok = key.issue_jwt sub: 'host/example', cidr: %w(fec0::/64)
|
12
|
-
|
13
|
-
expect(tok).to be_frozen
|
14
|
-
|
15
|
-
expect(tok.header).to eq \
|
16
|
-
alg: 'conjur.org/slosilo/v2',
|
17
|
-
kid: key_fingerprint
|
18
|
-
expect(tok.claims).to eq \
|
19
|
-
iat: 1401938552,
|
20
|
-
sub: 'host/example',
|
21
|
-
cidr: ['fec0::/64']
|
22
|
-
|
23
|
-
expect(key.verify_signature tok.string_to_sign, tok.signature).to be_truthy
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe Slosilo::JWT do
|
29
|
-
context "with a signed token" do
|
30
|
-
let(:signature) { 'very signed, such alg' }
|
31
|
-
subject(:token) { Slosilo::JWT.new test: "token" }
|
32
|
-
before do
|
33
|
-
allow(Time).to receive(:now) { DateTime.parse('2014-06-04 23:22:32 -0400').to_time }
|
34
|
-
token.add_signature(alg: 'test-sig') { signature }
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'allows conversion to JSON representation with #to_json' do
|
38
|
-
json = JSON.load token.to_json
|
39
|
-
expect(JSON.load Base64.urlsafe_decode64 json['protected']).to eq \
|
40
|
-
'alg' => 'test-sig'
|
41
|
-
expect(JSON.load Base64.urlsafe_decode64 json['payload']).to eq \
|
42
|
-
'iat' => 1401938552, 'test' => 'token'
|
43
|
-
expect(Base64.urlsafe_decode64 json['signature']).to eq signature
|
44
|
-
end
|
45
|
-
|
46
|
-
it 'allows conversion to compact representation with #to_s' do
|
47
|
-
h, c, s = token.to_s.split '.'
|
48
|
-
expect(JSON.load Base64.urlsafe_decode64 h).to eq \
|
49
|
-
'alg' => 'test-sig'
|
50
|
-
expect(JSON.load Base64.urlsafe_decode64 c).to eq \
|
51
|
-
'iat' => 1401938552, 'test' => 'token'
|
52
|
-
expect(Base64.urlsafe_decode64 s).to eq signature
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
describe '#to_json' do
|
57
|
-
it "passes any parameters" do
|
58
|
-
token = Slosilo::JWT.new
|
59
|
-
allow(token).to receive_messages \
|
60
|
-
header: :header,
|
61
|
-
claims: :claims,
|
62
|
-
signature: :signature
|
63
|
-
expect_any_instance_of(Hash).to receive(:to_json).with :testing
|
64
|
-
expect(token.to_json :testing)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe '()' do
|
69
|
-
include_context "with example key"
|
70
|
-
|
71
|
-
it 'understands both serializations' do
|
72
|
-
[COMPACT_TOKEN, JSON_TOKEN].each do |token|
|
73
|
-
token = Slosilo::JWT token
|
74
|
-
expect(token.header).to eq \
|
75
|
-
'typ' => 'JWT',
|
76
|
-
'alg' => 'conjur.org/slosilo/v2',
|
77
|
-
'kid' => key_fingerprint
|
78
|
-
expect(token.claims).to eq \
|
79
|
-
'sub' => 'host/example',
|
80
|
-
'iat' => 1401938552,
|
81
|
-
'exp' => 1401938552 + 60*60,
|
82
|
-
'cidr' => ['fec0::/64']
|
83
|
-
expect(key.verify_signature token.string_to_sign, token.signature).to be_truthy
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'is a noop if already parsed' do
|
88
|
-
token = Slosilo::JWT COMPACT_TOKEN
|
89
|
-
expect(Slosilo::JWT token).to eq token
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'raises ArgumentError on failure to convert' do
|
93
|
-
expect { Slosilo::JWT "foo bar" }.to raise_error ArgumentError
|
94
|
-
expect { Slosilo::JWT elite: 31337 }.to raise_error ArgumentError
|
95
|
-
expect { Slosilo::JWT "foo.bar.xyzzy" }.to raise_error ArgumentError
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
COMPACT_TOKEN = "eyJ0eXAiOiJKV1QiLCJhbGciOiJjb25qdXIub3JnL3Nsb3NpbG8vdjIiLCJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=.eyJzdWIiOiJob3N0L2V4YW1wbGUiLCJjaWRyIjpbImZlYzA6Oi82NCJdLCJleHAiOjE0MDE5NDIxNTIsImlhdCI6MTQwMTkzODU1Mn0=.qSxy6gx0DbiIc-Wz_vZhBsYi1SCkHhzxfMGPnnG6MTqjlzy7ntmlU2H92GKGoqCRo6AaNLA_C3hA42PeEarV5nMoTj8XJO_kwhrt2Db2OX4u83VS0_enoztWEZG5s45V0Lv71lVR530j4LD-hpqhm_f4VuISkeH84u0zX7s1zKOlniuZP-abCAHh0htTnrVz9wKG0VywkCUmWYyNNqC2h8PRf64SvCWcQ6VleHpjO-ms8OeTw4ZzRbzKMi0mL6eTmQlbT3PeBArUaS0pNJPg9zdDQaL2XDOofvQmj6Yy_8RA4eCt9HEfTYEdriVqK-_9QCspbGzFVn9GTWf51MRi5dngV9ItsDoG9ktDtqFuMttv7TcqjftsIHZXZsAZ175E".freeze
|
100
|
-
|
101
|
-
JSON_TOKEN = "{\"protected\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJjb25qdXIub3JnL3Nsb3NpbG8vdjIiLCJraWQiOiIxMDdiZGI4NTAxYzQxOWZhZDJmZGIyMGI0NjdkNGQwYTYyYTE2YTk4YzM1ZjJkYTBlYjNiMWZmOTI5Nzk1YWQ5In0=\",\"payload\":\"eyJzdWIiOiJob3N0L2V4YW1wbGUiLCJjaWRyIjpbImZlYzA6Oi82NCJdLCJleHAiOjE0MDE5NDIxNTIsImlhdCI6MTQwMTkzODU1Mn0=\",\"signature\":\"qSxy6gx0DbiIc-Wz_vZhBsYi1SCkHhzxfMGPnnG6MTqjlzy7ntmlU2H92GKGoqCRo6AaNLA_C3hA42PeEarV5nMoTj8XJO_kwhrt2Db2OX4u83VS0_enoztWEZG5s45V0Lv71lVR530j4LD-hpqhm_f4VuISkeH84u0zX7s1zKOlniuZP-abCAHh0htTnrVz9wKG0VywkCUmWYyNNqC2h8PRf64SvCWcQ6VleHpjO-ms8OeTw4ZzRbzKMi0mL6eTmQlbT3PeBArUaS0pNJPg9zdDQaL2XDOofvQmj6Yy_8RA4eCt9HEfTYEdriVqK-_9QCspbGzFVn9GTWf51MRi5dngV9ItsDoG9ktDtqFuMttv7TcqjftsIHZXZsAZ175E\"}".freeze
|
102
|
-
end
|
data/test.sh
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
#!/bin/bash -xe
|
2
|
-
|
3
|
-
|
4
|
-
echo "==> Docker Run"
|
5
|
-
docker run --rm --volume $PWD:/app --workdir /app cyberark/ubuntu-ruby-builder bash -c 'git config --global --add safe.directory /app && bundle && ls -ltra && bundle exec rake jenkins' || :
|
6
|
-
|
7
|
-
echo "==> CP Coverage to Spec"
|
8
|
-
cp -r coverage spec
|