infisical-sdk 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 76ccc0dbd846bf88995c037fca57e95d0e4bb170920fb671c5647e0fe65a4db9
4
+ data.tar.gz: a4af651d6824cf8978cb20f15d7ad9bf04df88a1c050d99ef4d5fb3042f12062
5
+ SHA512:
6
+ metadata.gz: 6f9b107f069c6c566e9cc27da137a7565866eb18ccd7f4bd39711fe0dd0195a294361084c6131d5eb4738f1549f0f5b344e9d3762aadcad8f96875c9fb7829d3
7
+ data.tar.gz: 57ebffb40d22abd61c4d06ce65d4880eab45959bfdbfb1e8dfa171936a449ef77e9f436b7c8eb8715db28c77af1a09137510d9beb236725d5403c557ea7f8ed0
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rubocop/rake_task'
5
+ require 'rspec/core/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ RuboCop::RakeTask.new
10
+
11
+ task default: :rubocop
data/Steepfile ADDED
@@ -0,0 +1,46 @@
1
+ D = Steep::Diagnostic
2
+ #
3
+ # target :lib do
4
+ # signature "sig"
5
+ #
6
+ # check "lib" # Directory name
7
+ # check "Gemfile" # File name
8
+ # check "app/models/**/*.rb" # Glob
9
+ # # ignore "lib/templates/*.rb"
10
+ #
11
+ # # library "pathname" # Standard libraries
12
+ # # library "strong_json" # Gems
13
+ #
14
+ # # configure_code_diagnostics(D::Ruby.default) # `default` diagnostics setting (applies by default)
15
+ # # configure_code_diagnostics(D::Ruby.strict) # `strict` diagnostics setting
16
+ # # configure_code_diagnostics(D::Ruby.lenient) # `lenient` diagnostics setting
17
+ # # configure_code_diagnostics(D::Ruby.silent) # `silent` diagnostics setting
18
+ # # configure_code_diagnostics do |hash| # You can setup everything yourself
19
+ # # hash[D::Ruby::NoMethod] = :information
20
+ # # end
21
+ # end
22
+
23
+ # target :test do
24
+ # signature "sig", "sig-private"
25
+ #
26
+ # check "test"
27
+ #
28
+ # # library "pathname" # Standard libraries
29
+ # end
30
+
31
+ target :app do
32
+ check 'lib'
33
+ signature 'sig'
34
+
35
+ library 'set', 'pathname'
36
+ ignore(
37
+ 'lib/schemas.rb',
38
+ 'lib/infisical_lib.rb',
39
+ 'lib/extended_schemas/schemas.rb'
40
+ )
41
+
42
+ configure_code_diagnostics do |hash| # You can setup everything yourself
43
+
44
+ hash[D::Ruby::UnknownConstant] = :information
45
+ end
46
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'infisical-sdk'
7
+ spec.version = InfisicalSDK::VERSION
8
+ spec.authors = ['Infisical Inc.']
9
+ spec.email = ['team@infisical.com']
10
+
11
+ spec.summary = 'Ruby SDK for interacting with the Infisical platform.'
12
+ spec.description = 'The official Infisical Ruby SDK.'
13
+ spec.homepage = 'https://infisical.com'
14
+ spec.required_ruby_version = '>= 2.7'
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/infisical/sdk'
18
+ spec.metadata['changelog_uri'] = 'https://infisical.com/docs/changelog/overview'
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/linux-arm64/**/*')
30
+ spec.files += Dir.glob('lib/macos-x64/**/*')
31
+ spec.files += Dir.glob('lib/windows-x64/**/*')
32
+ spec.files += Dir.glob('lib/macos-arm64/**/*')
33
+ spec.files += Dir.glob('lib/schemas.rb')
34
+
35
+ spec.bindir = 'exe'
36
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
37
+ spec.require_paths = ['lib']
38
+
39
+ # Uncomment to register a new dependency of your gem
40
+ # spec.add_dependency "example-gem", "~> 1.0"
41
+ spec.add_dependency 'dry-struct', '~> 1.6'
42
+ spec.add_dependency 'dry-types', '~> 1.7'
43
+ spec.add_dependency 'ffi', '~> 1.15'
44
+ spec.add_dependency 'json', '~> 2.6'
45
+ spec.add_dependency 'rake', '~> 13.0'
46
+ spec.add_dependency 'rubocop', '~> 1.21'
47
+
48
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative '../extended_schemas/schemas'
5
+
6
+ module InfisicalSDK
7
+ # Manage Infisical secrets.
8
+ class AuthClient
9
+ def initialize(command_runner)
10
+ @command_runner = command_runner
11
+ end
12
+
13
+ def universal_auth(client_id:, client_secret:)
14
+ response = run_command(universal_auth_login: UniversalAuthMethod.new(
15
+ client_id: client_id,
16
+ client_secret: client_secret
17
+ ))
18
+
19
+ handle_auth_response(response)
20
+ end
21
+
22
+ def kubernetes_auth(identity_id:, service_account_token_path:)
23
+
24
+ response = run_command(kubernetes_auth_login: KubernetesAuthMethod.new(
25
+ identity_id: identity_id,
26
+ service_account_token_path: service_account_token_path
27
+ ))
28
+
29
+ handle_auth_response(response)
30
+ end
31
+
32
+ def azure_auth(identity_id:)
33
+
34
+ response = run_command(azure_auth_login: AzureAuthMethod.new(
35
+ identity_id: identity_id
36
+ ))
37
+
38
+ handle_auth_response(response)
39
+ end
40
+
41
+ def gcp_id_token_auth(identity_id:)
42
+
43
+ response = run_command(gcp_id_token_auth_login: GCPIDTokenAuthMethod.new(
44
+ identity_id: identity_id
45
+ ))
46
+
47
+ handle_auth_response(response)
48
+ end
49
+
50
+ def gcp_iam_auth(identity_id:, service_account_key_file_path:)
51
+
52
+ response = run_command(gcp_iam_auth_login: GCPIamAuthMethod.new(
53
+ identity_id: identity_id,
54
+ service_account_key_file_path: service_account_key_file_path
55
+ ))
56
+
57
+ handle_auth_response(response)
58
+ end
59
+
60
+ def aws_iam_auth(identity_id:)
61
+
62
+ response = run_command(aws_iam_auth_login: AWSIamAuthMethod.new(
63
+ identity_id: identity_id
64
+ ))
65
+
66
+ handle_auth_response(response)
67
+ end
68
+
69
+ private
70
+
71
+ def error_handler(response)
72
+
73
+ # If the response is successful, we return without raising errors.
74
+ if response.key?('success') && response['success'] == true && response.key?('data')
75
+ return
76
+ end
77
+
78
+ if response['errorMessage']
79
+ raise InfisicalError, response['errorMessage'] if response.key?('errorMessage')
80
+ else
81
+ raise InfisicalError, 'Error while getting response'
82
+ end
83
+ end
84
+
85
+ def handle_auth_response(response)
86
+ auth_response = ResponseForAccessTokenSuccessResponse.from_json!(response).to_dynamic
87
+ error_handler(auth_response)
88
+
89
+ auth_response['data']
90
+ end
91
+
92
+ def run_command(command)
93
+ response = @command_runner.run(InfisicalCommands.new(command))
94
+ raise InfisicalError, 'Error getting response' if response.nil?
95
+
96
+ response
97
+ end
98
+ end
99
+ end
100
+
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/MethodLength
4
+ # rubocop:disable Naming/MethodParameterName
5
+
6
+
7
+
8
+ require 'json'
9
+ require_relative '../extended_schemas/schemas'
10
+
11
+
12
+ module InfisicalSDK
13
+ # Perform encryption
14
+ class EncryptionClient
15
+ def initialize(command_runner)
16
+ @command_runner = command_runner
17
+ end
18
+
19
+ def encrypt_symmetric(data:, key:)
20
+ response = run_command(encrypt_symmetric: EncryptSymmetricOptions.new(
21
+ key: key,
22
+ plaintext: data,
23
+ ))
24
+
25
+ encrypt_response = ResponseForEncryptSymmetricResponse.from_json!(response).to_dynamic
26
+ error_handler(encrypt_response)
27
+
28
+
29
+ encrypt_response['data']
30
+ end
31
+
32
+ def decrypt_symmetric(
33
+ ciphertext:,
34
+ iv:,
35
+ tag:,
36
+ key:
37
+ )
38
+
39
+ response = run_command(decrypt_symmetric: DecryptSymmetricOptions.new(
40
+ ciphertext: ciphertext,
41
+ iv: iv,
42
+ tag: tag,
43
+ key: key
44
+ ))
45
+
46
+ decrypt_response = ResponseForDecryptSymmetricResponse.from_json!(response).to_dynamic
47
+ error_handler(decrypt_response)
48
+
49
+ decrypt_response['data']['decrypted']
50
+ end
51
+
52
+ def create_symmetric_key
53
+ response = run_command(create_symmetric_key: ArbitraryOptions.new(
54
+ data: ''
55
+ ))
56
+
57
+ key_response = ResponseForCreateSymmetricKeyResponse.from_json!(response).to_dynamic
58
+ error_handler(key_response)
59
+
60
+ key_response['data']['key']
61
+ end
62
+
63
+ private
64
+
65
+ def error_handler(response)
66
+
67
+ # If the response is successful, we return without raising errors.
68
+ if response.key?('success') && response['success'] == true && response.key?('data')
69
+ return
70
+ end
71
+
72
+ if response['errorMessage']
73
+ raise InfisicalError, response['errorMessage'] if response.key?('errorMessage')
74
+ else
75
+ raise InfisicalError, 'Error while getting response'
76
+ end
77
+ end
78
+
79
+ def run_command(command)
80
+ response = @command_runner.run(InfisicalCommands.new(command))
81
+ raise InfisicalError, 'Error getting response' if response.nil?
82
+
83
+ response
84
+ end
85
+ end
86
+ end
87
+
88
+ # rubocop:enable Metrics/MethodLength
89
+ # rubocop:enable Naming/MethodParameterName
90
+
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ require_relative '../extended_schemas/schemas'
6
+
7
+ module InfisicalSDK
8
+ # Manage Infisical secrets.
9
+ class SecretsClient
10
+ def initialize(command_runner)
11
+ @command_runner = command_runner
12
+ end
13
+
14
+ # rubocop:disable Metrics/ParameterLists
15
+ # rubocop:disable Metrics/MethodLength
16
+ def get(
17
+ secret_name:,
18
+ project_id:,
19
+ environment:,
20
+ path: nil,
21
+ include_imports: nil,
22
+ type: nil
23
+ )
24
+
25
+ response = run_command(get_secret: GetSecretOptions.new(
26
+ secret_name: secret_name,
27
+ project_id: project_id,
28
+ environment: environment,
29
+ path: path,
30
+ include_imports: include_imports,
31
+ get_secret_options_type: type
32
+ ))
33
+
34
+ secrets_response = ResponseForGetSecretResponse.from_json!(response).to_dynamic
35
+ error_handler(secrets_response)
36
+
37
+
38
+ secrets_response['data']['secret']
39
+ end
40
+
41
+ def list(
42
+ project_id:,
43
+ environment:,
44
+ path: nil ,
45
+ attach_to_process_env: nil,
46
+ expand_secret_references: nil,
47
+ recursive: nil,
48
+ include_imports: nil
49
+ )
50
+ response = run_command(list_secrets: ListSecretsOptions.new(
51
+ project_id: project_id,
52
+ environment: environment,
53
+ path: path,
54
+ include_imports: include_imports,
55
+ recursive: recursive,
56
+ attach_to_process_env: attach_to_process_env,
57
+ expand_secret_references: expand_secret_references,
58
+ ))
59
+
60
+ secrets_response = ResponseForListSecretsResponse.from_json!(response).to_dynamic
61
+ error_handler(secrets_response)
62
+
63
+ secrets_response['data']['secrets']
64
+ end
65
+
66
+ def update(
67
+ secret_name:,
68
+ secret_value:,
69
+ project_id:,
70
+ environment:,
71
+ path: nil,
72
+ skip_multiline_encoding: nil,
73
+ type: nil
74
+ )
75
+ response = run_command(update_secret: UpdateSecretOptions.new(
76
+ secret_name: secret_name,
77
+ secret_value: secret_value,
78
+ project_id: project_id,
79
+ environment: environment,
80
+ path: path,
81
+ skip_multiline_encoding: skip_multiline_encoding,
82
+ update_secret_options_type: type
83
+ ))
84
+
85
+ secrets_response = ResponseForUpdateSecretResponse.from_json!(response).to_dynamic
86
+ error_handler(secrets_response)
87
+
88
+
89
+ secrets_response['data']['secret']
90
+ end
91
+
92
+ def create(
93
+ secret_name:,
94
+ secret_value:,
95
+ project_id:,
96
+ environment:,
97
+ secret_comment: nil,
98
+ path: nil,
99
+ skip_multiline_encoding: nil,
100
+ type: nil
101
+
102
+ )
103
+
104
+ response = run_command(create_secret: CreateSecretOptions.new(
105
+ secret_name: secret_name,
106
+ secret_value: secret_value,
107
+ secret_comment: secret_comment,
108
+ project_id: project_id,
109
+ environment: environment,
110
+ skip_multiline_encoding: skip_multiline_encoding,
111
+ path: path,
112
+ create_secret_options_type: type
113
+ ))
114
+
115
+ secrets_response = ResponseForCreateSecretResponse.from_json!(response).to_dynamic
116
+ error_handler(secrets_response)
117
+
118
+
119
+ secrets_response['data']['secret']
120
+ end
121
+
122
+ def delete(
123
+ secret_name:,
124
+ project_id:,
125
+ environment:,
126
+ path: nil,
127
+ type: nil
128
+ )
129
+ response = run_command(delete_secret: DeleteSecretOptions.new(
130
+ secret_name: secret_name,
131
+ project_id: project_id,
132
+ environment: environment,
133
+ path: path,
134
+ delete_secret_options_type: type
135
+ ))
136
+
137
+ secrets_response = ResponseForDeleteSecretResponse.from_json!(response).to_dynamic
138
+ error_handler(secrets_response)
139
+
140
+ secrets_response['data']['secret']
141
+ end
142
+
143
+ private
144
+
145
+ def error_handler(response)
146
+
147
+ # If the response is successful, we return without raising errors.
148
+ if response.key?('success') && response['success'] == true && response.key?('data')
149
+ return
150
+ end
151
+
152
+ if response['errorMessage']
153
+ raise InfisicalError, response['errorMessage'] if response.key?('errorMessage')
154
+ else
155
+ raise InfisicalError, 'Error while getting response'
156
+ end
157
+ end
158
+
159
+ def run_command(command)
160
+ response = @command_runner.run(InfisicalCommands.new(command))
161
+ raise InfisicalError, 'Error getting response' if response.nil?
162
+
163
+ response
164
+ end
165
+ end
166
+ end
167
+
168
+ # rubocop:enable Metrics/ParameterLists
169
+ # rubocop:enable Metrics/MethodLength
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfisicalSDK
4
+ # Run base SDK commands
5
+ class CommandRunner
6
+ def initialize(infisical_sdk, handle)
7
+ @infisical_sdk = infisical_sdk
8
+ @handle = handle
9
+ end
10
+
11
+ # @param [Dry-Struct] cmd
12
+ def run(cmd)
13
+ @infisical_sdk.run_command(cmd.to_json, @handle)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,44 @@
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 'infisical_lib'
9
+ require_relative 'infisical_error'
10
+ require_relative 'command_runner'
11
+ require_relative 'clients/secrets'
12
+ require_relative 'clients/auth'
13
+ require_relative 'clients/encryption'
14
+
15
+ module InfisicalSDK
16
+ class InfisicalClient
17
+ attr_reader :infisical, :command_runner, :secrets, :auth, :encryption
18
+
19
+ def initialize(site_url = nil, cache_ttl = 300)
20
+ settings = ClientSettings.new(
21
+ # We preset these values or we'll get type validation errors (thanks Quicktype!)
22
+ access_token: nil,
23
+ client_secret: nil,
24
+ client_id: nil,
25
+ auth: nil,
26
+ user_agent: 'infisical-ruby-sdk',
27
+ cache_ttl: cache_ttl,
28
+ site_url: site_url
29
+ )
30
+
31
+
32
+ @infisical = InfisicalLib
33
+ @handle = @infisical.init(settings.to_dynamic.compact.to_json)
34
+ @command_runner = CommandRunner.new(@infisical, @handle)
35
+ @secrets = SecretsClient.new(@command_runner)
36
+ @auth = AuthClient.new(@command_runner)
37
+ @encryption = EncryptionClient.new(@command_runner)
38
+ end
39
+
40
+ def free_mem
41
+ @infisical.free_mem(@handle)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfisicalSDK
4
+ # Infisical Error
5
+ class InfisicalError < StandardError
6
+ def initialize(message = 'Failed to get get response')
7
+ super(message)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ffi'
4
+
5
+ module InfisicalSDK
6
+ # C wrapper for Ruby SDK
7
+ module InfisicalLib
8
+ extend FFI::Library
9
+
10
+ def self.mac_with_intel?
11
+ `uname -m`.strip == 'x86_64'
12
+ end
13
+
14
+ def self.linux_arm64?
15
+ RUBY_PLATFORM.include?('linux') && %w[aarch64 arm64].any? { |arch| RUBY_PLATFORM.include?(arch) }
16
+ end
17
+
18
+ ffi_lib case RUBY_PLATFORM
19
+ when /darwin/
20
+ local_file = if mac_with_intel?
21
+ File.expand_path('macos-x64/libinfisical_c.dylib', __dir__)
22
+ else
23
+ File.expand_path('macos-arm64/libinfisical_c.dylib', __dir__)
24
+ end
25
+ File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libinfisical_c.dylib', __dir__)
26
+ when /linux/
27
+ local_file = if linux_arm64?
28
+ File.expand_path('linux-arm64/libinfisical_c.so', __dir__)
29
+ else
30
+ File.expand_path('linux-x64/libinfisical_c.so', __dir__)
31
+ end
32
+ File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/libinfisical_c.so', __dir__)
33
+ when /mswin|mingw/
34
+ local_file = File.expand_path('windows-x64/infisical_c.dll', __dir__)
35
+ File.exist?(local_file) ? local_file : File.expand_path('../../../../target/debug/infisical_c.dll', __dir__)
36
+ else
37
+ raise "Unsupported platform: #{RUBY_PLATFORM}"
38
+ end
39
+
40
+ attach_function :init, [:string], :pointer
41
+ attach_function :run_command, %i[string pointer], :string
42
+ attach_function :free_mem, [:pointer], :void
43
+ end
44
+ end
Binary file
Binary file
Binary file