bitwarden-sdk-secrets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Rakefile +11 -0
- data/bitwarden-sdk-secrets.gemspec +47 -0
- data/lib/bitwarden-sdk-secrets.rb +56 -0
- data/lib/bitwarden_error.rb +9 -0
- data/lib/bitwarden_lib.rb +35 -0
- data/lib/command_runner.rb +15 -0
- data/lib/extended_schemas/schemas.rb +64 -0
- data/lib/linux-x64/libbitwarden_c.so +0 -0
- data/lib/macos-arm64/libbitwarden_c.dylib +0 -0
- data/lib/macos-x64/libbitwarden_c.dylib +0 -0
- data/lib/projects.rb +116 -0
- data/lib/schemas.rb +3450 -0
- data/lib/secrets.rb +124 -0
- data/lib/version.rb +5 -0
- data/lib/windows-x64/bitwarden_c.dll +0 -0
- data/sig/bitwarden-sdk.rbs +13 -0
- data/sig/bitwarden_settings.rbs +8 -0
- data/sig/command_runner.rbs +4 -0
- data/sig/projects_client.rbs +17 -0
- data/sig/sdk.rbs +3 -0
- data/sig/secrets_client.rbs +18 -0
- metadata +150 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a4a8efa2366ad5c6568ce9ec284857674c1b1730263bd538096a2861031ae833
|
4
|
+
data.tar.gz: 7e15ebee50e29c57357f958f1273fdda182035a490b555510cd95de0f49e14b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ac31e0a25f1ee16b2db1e2949cca718cd268a4ad0b2f18c28ffee48b1cf3ab5d3855bb771869037f00161255529f8d0715f628197e5309391162bca94e799c79
|
7
|
+
data.tar.gz: 52e926afe59c3d545d0d5441dc2cb356491291a7ffffa6af2ef7a61006dbf6ab3eef8d6662faf87eb1811d4c5eaf17a5a8756627252304868fb3b589ab0070ea
|
data/Rakefile
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'bitwarden-sdk-secrets'
|
7
|
+
spec.version = BitwardenSDKSecrets::VERSION
|
8
|
+
spec.authors = ['Bitwarden Inc.']
|
9
|
+
spec.email = ['hello@bitwarden_sdk.com']
|
10
|
+
|
11
|
+
spec.summary = 'Bitwarden Secrets Manager SDK.'
|
12
|
+
spec.description = 'Ruby wrapper for Bitwarden secrets manager SDK.'
|
13
|
+
spec.homepage = 'https://bitwarden.com/products/secrets-manager/'
|
14
|
+
spec.required_ruby_version = '>= 3.0.0'
|
15
|
+
|
16
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
17
|
+
spec.metadata['source_code_uri'] = 'https://github.com/bitwarden/sdk'
|
18
|
+
spec.metadata['changelog_uri'] = 'https://github.com/bitwarden/sdk/blob/main/languages/ruby/CHANGELOG.md'
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(__dir__) do
|
23
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
24
|
+
(File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git Gemfile])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
spec.files += Dir.glob('lib/linux-x64/**/*')
|
29
|
+
spec.files += Dir.glob('lib/macos-x64/**/*')
|
30
|
+
spec.files += Dir.glob('lib/windows-x64/**/*')
|
31
|
+
spec.files += Dir.glob('lib/macos-arm64/**/*')
|
32
|
+
spec.files += Dir.glob('lib/schemas.rb')
|
33
|
+
|
34
|
+
spec.bindir = 'exe'
|
35
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
36
|
+
spec.require_paths = ['lib']
|
37
|
+
|
38
|
+
# Uncomment to register a new dependency of your gem
|
39
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
40
|
+
spec.add_dependency 'dry-struct', '~> 1.6'
|
41
|
+
spec.add_dependency 'dry-types', '~> 1.7'
|
42
|
+
spec.add_dependency 'ffi', '~> 1.15'
|
43
|
+
spec.add_dependency 'json', '~> 2.6'
|
44
|
+
spec.add_dependency 'rake', '~> 13.0'
|
45
|
+
spec.add_dependency 'rubocop', '~> 1.21'
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require 'dry-types'
|
5
|
+
|
6
|
+
require_relative 'schemas'
|
7
|
+
require_relative 'extended_schemas/schemas'
|
8
|
+
require_relative 'command_runner'
|
9
|
+
require_relative 'bitwarden_lib'
|
10
|
+
require_relative 'bitwarden_error'
|
11
|
+
require_relative 'projects'
|
12
|
+
require_relative 'secrets'
|
13
|
+
|
14
|
+
module BitwardenSDKSecrets
|
15
|
+
class BitwardenSettings
|
16
|
+
attr_accessor :api_url, :identity_url
|
17
|
+
|
18
|
+
def initialize(api_url, identity_url)
|
19
|
+
# if api_url.nil? || identity_url.nil?
|
20
|
+
# raise ArgumentError, "api_url and identity_url cannot be nil"
|
21
|
+
# end
|
22
|
+
|
23
|
+
@api_url = api_url
|
24
|
+
@identity_url = identity_url
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class BitwardenClient
|
29
|
+
attr_reader :bitwarden, :project_client, :secrets_client
|
30
|
+
|
31
|
+
def initialize(bitwarden_settings)
|
32
|
+
client_settings = ClientSettings.new(
|
33
|
+
api_url: bitwarden_settings.api_url,
|
34
|
+
identity_url: bitwarden_settings.identity_url,
|
35
|
+
user_agent: 'Bitwarden RUBY-SDK',
|
36
|
+
device_type: nil
|
37
|
+
)
|
38
|
+
|
39
|
+
@bitwarden = BitwardenLib
|
40
|
+
@handle = @bitwarden.init(client_settings.to_dynamic.compact.to_json)
|
41
|
+
@command_runner = CommandRunner.new(@bitwarden, @handle)
|
42
|
+
@project_client = ProjectsClient.new(@command_runner)
|
43
|
+
@secrets_client = SecretsClient.new(@command_runner)
|
44
|
+
end
|
45
|
+
|
46
|
+
def access_token_login(access_token, state_file = nil)
|
47
|
+
access_token_request = AccessTokenLoginRequest.new(access_token: access_token, state_file: state_file)
|
48
|
+
@command_runner.run(SelectiveCommand.new(access_token_login: access_token_request))
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
def free_mem
|
53
|
+
@bitwarden.free_mem(@handle)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module BitwardenSDKSecrets
|
6
|
+
module BitwardenLib
|
7
|
+
extend FFI::Library
|
8
|
+
|
9
|
+
def self.mac_with_intel?
|
10
|
+
`uname -m`.strip == 'x86_64'
|
11
|
+
end
|
12
|
+
|
13
|
+
ffi_lib case RUBY_PLATFORM
|
14
|
+
when /darwin/
|
15
|
+
local_file = if mac_with_intel?
|
16
|
+
File.expand_path('macos-x64/libbitwarden_c.dylib', __dir__)
|
17
|
+
else
|
18
|
+
File.expand_path('macos-arm64/libbitwarden_c.dylib', __dir__)
|
19
|
+
end
|
20
|
+
File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.dylib', __dir__)
|
21
|
+
when /linux/
|
22
|
+
local_file = File.expand_path('linux-x64/libbitwarden_c.so', __dir__)
|
23
|
+
File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libbitwarden_c.so', __dir__)
|
24
|
+
when /mswin|mingw/
|
25
|
+
local_file = File.expand_path('windows-x64/bitwarden_c.dll', __dir__)
|
26
|
+
File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/bitwarden_c.dll', __dir__)
|
27
|
+
else
|
28
|
+
raise "Unsupported platform: #{RUBY_PLATFORM}"
|
29
|
+
end
|
30
|
+
|
31
|
+
attach_function :init, [:string], :pointer
|
32
|
+
attach_function :run_command, %i[string pointer], :string
|
33
|
+
attach_function :free_mem, [:pointer], :void
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BitwardenSDKSecrets
|
4
|
+
class CommandRunner
|
5
|
+
def initialize(bitwarden_sdk, handle)
|
6
|
+
@bitwarden_sdk = bitwarden_sdk
|
7
|
+
@handle = handle
|
8
|
+
end
|
9
|
+
|
10
|
+
# @param [Dry-Struct] cmd
|
11
|
+
def run(cmd)
|
12
|
+
@bitwarden_sdk.run_command(cmd.to_json, @handle)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
|
2
|
+
module BitwardenSDKSecrets
|
3
|
+
class SelectiveCommand < Command
|
4
|
+
attribute :password_login, PasswordLoginRequest.optional.default(nil)
|
5
|
+
attribute :api_key_login, APIKeyLoginRequest.optional.default(nil)
|
6
|
+
attribute :access_token_login, AccessTokenLoginRequest.optional.default(nil)
|
7
|
+
attribute :get_user_api_key, SecretVerificationRequest.optional.default(nil)
|
8
|
+
attribute :fingerprint, FingerprintRequest.optional.default(nil)
|
9
|
+
attribute :sync, SyncRequest.optional.default(nil)
|
10
|
+
attribute :secrets, SecretsCommand.optional.default(nil)
|
11
|
+
attribute :projects, ProjectsCommand.optional.default(nil)
|
12
|
+
|
13
|
+
def to_dynamic
|
14
|
+
{
|
15
|
+
"passwordLogin" => password_login&.to_dynamic,
|
16
|
+
"apiKeyLogin" => api_key_login&.to_dynamic,
|
17
|
+
"accessTokenLogin" => access_token_login&.to_dynamic,
|
18
|
+
"getUserApiKey" => get_user_api_key&.to_dynamic,
|
19
|
+
"fingerprint" => fingerprint&.to_dynamic,
|
20
|
+
"sync" => sync&.to_dynamic,
|
21
|
+
"secrets" => secrets&.to_dynamic,
|
22
|
+
"projects" => projects&.to_dynamic,
|
23
|
+
}.compact
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class SelectiveProjectsCommand < ProjectsCommand
|
28
|
+
attribute :get, ProjectGetRequest.optional.default(nil)
|
29
|
+
attribute :create, ProjectCreateRequest.optional.default(nil)
|
30
|
+
attribute :list, ProjectsListRequest.optional.default(nil)
|
31
|
+
attribute :update, ProjectPutRequest.optional.default(nil)
|
32
|
+
attribute :delete, ProjectsDeleteRequest.optional.default(nil)
|
33
|
+
|
34
|
+
def to_dynamic
|
35
|
+
{
|
36
|
+
"get" => get&.to_dynamic,
|
37
|
+
"create" => create&.to_dynamic,
|
38
|
+
"list" => list&.to_dynamic,
|
39
|
+
"update" => update&.to_dynamic,
|
40
|
+
"delete" => delete&.to_dynamic,
|
41
|
+
}.compact
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class SelectiveSecretsCommand < SecretsCommand
|
46
|
+
attribute :get, SecretGetRequest.optional.default(nil)
|
47
|
+
attribute :get_by_ids, SecretsGetRequest.optional.default(nil)
|
48
|
+
attribute :create, SecretCreateRequest.optional.default(nil)
|
49
|
+
attribute :list, SecretIdentifiersRequest.optional.default(nil)
|
50
|
+
attribute :update, SecretPutRequest.optional.default(nil)
|
51
|
+
attribute :delete, SecretsDeleteRequest.optional.default(nil)
|
52
|
+
|
53
|
+
def to_dynamic
|
54
|
+
{
|
55
|
+
"get" => get&.to_dynamic,
|
56
|
+
"getByIds" => get_by_ids&.to_dynamic,
|
57
|
+
"create" => create&.to_dynamic,
|
58
|
+
"list" => list&.to_dynamic,
|
59
|
+
"update" => update&.to_dynamic,
|
60
|
+
"delete" => delete&.to_dynamic,
|
61
|
+
}.compact
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/lib/projects.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'bitwarden_error'
|
4
|
+
|
5
|
+
module BitwardenSDKSecrets
|
6
|
+
class ProjectsClient
|
7
|
+
def initialize(command_runner)
|
8
|
+
@command_runner = command_runner
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_project(project_name, organization_id)
|
12
|
+
project_create_request = ProjectCreateRequest.new(
|
13
|
+
project_create_request_name: project_name,
|
14
|
+
organization_id: organization_id
|
15
|
+
)
|
16
|
+
command = create_command(
|
17
|
+
create: project_create_request
|
18
|
+
)
|
19
|
+
response = parse_response(command)
|
20
|
+
|
21
|
+
projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic
|
22
|
+
|
23
|
+
if projects_response.key?('success') && projects_response['success'] == true &&
|
24
|
+
projects_response.key?('data')
|
25
|
+
return projects_response['data']
|
26
|
+
end
|
27
|
+
|
28
|
+
error_response(projects_response)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get(project_id)
|
32
|
+
project_get_request = ProjectGetRequest.new(id: project_id)
|
33
|
+
command = create_command(get: project_get_request)
|
34
|
+
response = parse_response(command)
|
35
|
+
|
36
|
+
projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic
|
37
|
+
|
38
|
+
if projects_response.key?('success') && projects_response['success'] == true &&
|
39
|
+
projects_response.key?('data')
|
40
|
+
return projects_response['data']
|
41
|
+
end
|
42
|
+
|
43
|
+
error_response(projects_response)
|
44
|
+
end
|
45
|
+
|
46
|
+
def list_projects(organization_id)
|
47
|
+
project_list_request = ProjectsListRequest.new(organization_id: organization_id)
|
48
|
+
command = create_command(list: project_list_request)
|
49
|
+
response = parse_response(command)
|
50
|
+
|
51
|
+
projects_response = ResponseForProjectsResponse.from_json!(response).to_dynamic
|
52
|
+
|
53
|
+
if projects_response.key?('success') && projects_response['success'] == true &&
|
54
|
+
projects_response.key?('data') && projects_response['data'].key?('data')
|
55
|
+
return projects_response['data']['data']
|
56
|
+
end
|
57
|
+
|
58
|
+
error_response(projects_response)
|
59
|
+
end
|
60
|
+
|
61
|
+
def update_project(id, project_put_request_name, organization_id)
|
62
|
+
project_put_request = ProjectPutRequest.new(
|
63
|
+
id: id,
|
64
|
+
project_put_request_name: project_put_request_name,
|
65
|
+
organization_id: organization_id
|
66
|
+
)
|
67
|
+
command = create_command(
|
68
|
+
update: project_put_request
|
69
|
+
)
|
70
|
+
response = parse_response(command)
|
71
|
+
|
72
|
+
projects_response = ResponseForProjectResponse.from_json!(response).to_dynamic
|
73
|
+
|
74
|
+
if projects_response.key?('success') && projects_response['success'] == true &&
|
75
|
+
projects_response.key?('data')
|
76
|
+
return projects_response['data']
|
77
|
+
end
|
78
|
+
|
79
|
+
error_response(projects_response)
|
80
|
+
end
|
81
|
+
|
82
|
+
def delete_projects(ids)
|
83
|
+
project_delete_request = ProjectsDeleteRequest.new(ids: ids)
|
84
|
+
command = create_command(delete: project_delete_request)
|
85
|
+
response = parse_response(command)
|
86
|
+
|
87
|
+
projects_response = ResponseForProjectsDeleteResponse.from_json!(response).to_dynamic
|
88
|
+
|
89
|
+
if projects_response.key?('success') && projects_response['success'] == true &&
|
90
|
+
projects_response.key?('data') && projects_response['data'].key?('data')
|
91
|
+
return projects_response['data']['data']
|
92
|
+
end
|
93
|
+
|
94
|
+
error_response(projects_response)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def error_response(response)
|
100
|
+
raise BitwardenError, response['errorMessage'] if response.key?('errorMessage')
|
101
|
+
|
102
|
+
raise BitwardenError, 'Error while getting response'
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_command(commands)
|
106
|
+
SelectiveCommand.new(projects: SelectiveProjectsCommand.new(commands))
|
107
|
+
end
|
108
|
+
|
109
|
+
def parse_response(command)
|
110
|
+
response = @command_runner.run(command)
|
111
|
+
raise BitwardenError, 'Error getting response' if response.nil?
|
112
|
+
|
113
|
+
response
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|