bcome 1.3.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bin/bcome +13 -8
- data/lib/bcome.rb +14 -11
- data/lib/objects/bcome/version.rb +19 -1
- data/lib/objects/bootup.rb +16 -7
- data/lib/objects/command/local.rb +2 -0
- data/lib/objects/config_factory.rb +3 -0
- data/lib/objects/driver/base.rb +52 -6
- data/lib/objects/driver/bucket.rb +6 -4
- data/lib/objects/driver/ec2.rb +45 -5
- data/lib/objects/driver/gcp.rb +168 -0
- data/lib/objects/driver/gcp/authentication/api_key.rb +6 -0
- data/lib/objects/driver/gcp/authentication/base.rb +36 -0
- data/lib/objects/driver/gcp/authentication/oauth.rb +96 -0
- data/lib/objects/driver/gcp/authentication/oauth_client_config.rb +22 -0
- data/lib/objects/driver/gcp/authentication/oauth_session_store.rb +22 -0
- data/lib/objects/driver/gcp/authentication/service_account.rb +62 -0
- data/lib/objects/driver/gcp/authentication/signet/service_account.rb +27 -0
- data/lib/objects/driver/gcp/authentication/utilities.rb +42 -0
- data/lib/objects/encryptor.rb +109 -24
- data/lib/objects/exception/argument_error_invoking_method_from_command_line.rb +8 -4
- data/lib/objects/exception/base.rb +21 -10
- data/lib/objects/exception/can_only_subselect_on_inventory.rb +8 -4
- data/lib/objects/exception/cannot_authenticate_to_gcp.rb +11 -0
- data/lib/objects/exception/cannot_find_internal_registry_klass.rb +8 -4
- data/lib/objects/exception/cannot_find_inventory.rb +11 -0
- data/lib/objects/exception/cannot_find_subselection_parent.rb +8 -4
- data/lib/objects/exception/cant_find_key_in_cloud_tags.rb +8 -4
- data/lib/objects/exception/cant_find_key_in_metadata.rb +8 -4
- data/lib/objects/exception/cant_find_proxy_host_by_identifier.rb +8 -4
- data/lib/objects/exception/cant_find_proxy_host_by_namespace.rb +8 -4
- data/lib/objects/exception/could_not_initiate_ssh_connection.rb +8 -4
- data/lib/objects/exception/could_not_initiate_ssh_connection_through_backend_proxy.rb +8 -4
- data/lib/objects/exception/could_not_retrieve_terraform_output.rb +11 -0
- data/lib/objects/exception/deprecation_warning.rb +9 -7
- data/lib/objects/exception/duplicate_command_line_argument_key.rb +8 -4
- data/lib/objects/exception/ec2_driver_missing_authorization_keys.rb +11 -0
- data/lib/objects/exception/ec2_driver_missing_provisioning_region.rb +8 -4
- data/lib/objects/exception/empty_namespace_tree.rb +11 -0
- data/lib/objects/exception/failed_to_run_local_command.rb +8 -4
- data/lib/objects/exception/gcp_auth_service_account_missing_credentials.rb +11 -0
- data/lib/objects/exception/generic.rb +11 -0
- data/lib/objects/exception/interactive_session_halt.rb +6 -2
- data/lib/objects/exception/invalid_bcome_breadcrumb.rb +8 -4
- data/lib/objects/exception/invalid_breadcrumb.rb +8 -4
- data/lib/objects/exception/invalid_context_command.rb +8 -4
- data/lib/objects/exception/invalid_gcp_authentication_scheme.rb +11 -0
- data/lib/objects/exception/invalid_identifier.rb +8 -4
- data/lib/objects/exception/invalid_machines_cache_config.rb +8 -4
- data/lib/objects/exception/invalid_matcher_query.rb +8 -4
- data/lib/objects/exception/invalid_meta_data_config.rb +8 -4
- data/lib/objects/exception/invalid_metadata_encryption_key.rb +8 -4
- data/lib/objects/exception/invalid_network_config.rb +8 -4
- data/lib/objects/exception/invalid_network_driver_type.rb +8 -4
- data/lib/objects/exception/invalid_port_forward_request.rb +11 -0
- data/lib/objects/exception/invalid_proxy_config.rb +8 -4
- data/lib/objects/exception/invalid_regexp_matcher_in_registry.rb +8 -4
- data/lib/objects/exception/invalid_registry_arguments_type.rb +8 -4
- data/lib/objects/exception/invalid_registry_command_name_length.rb +8 -4
- data/lib/objects/exception/invalid_registry_data_config.rb +8 -4
- data/lib/objects/exception/invalid_restriction_key_in_registry.rb +8 -4
- data/lib/objects/exception/invalid_ssh_config.rb +8 -4
- data/lib/objects/exception/inventories_cannot_have_subviews.rb +8 -4
- data/lib/objects/exception/malformed_command_line_arguments.rb +8 -4
- data/lib/objects/exception/method_invocation_requires_parameter.rb +8 -4
- data/lib/objects/exception/method_name_conflict_in_registry.rb +8 -4
- data/lib/objects/exception/missing_argument_for_registry_command.rb +8 -4
- data/lib/objects/exception/missing_description_on_view.rb +8 -4
- data/lib/objects/exception/missing_execute_on_registry_object.rb +8 -4
- data/lib/objects/exception/missing_gcp_authentication_scheme.rb +11 -0
- data/lib/objects/exception/missing_gcp_service_account_credentials_filename.rb +11 -0
- data/lib/objects/exception/missing_gcp_service_scopes.rb +11 -0
- data/lib/objects/exception/missing_identifier_on_view.rb +8 -4
- data/lib/objects/exception/missing_inventory_contributors.rb +11 -0
- data/lib/objects/exception/missing_ip_address_on_server.rb +8 -4
- data/lib/objects/exception/missing_network_config.rb +8 -4
- data/lib/objects/exception/missing_or_invalid_client_secrets.rb +11 -0
- data/lib/objects/exception/missing_params_for_rsync.rb +8 -4
- data/lib/objects/exception/missing_params_for_scp.rb +8 -4
- data/lib/objects/exception/missing_subselection_key.rb +8 -4
- data/lib/objects/exception/missing_type_on_view.rb +8 -4
- data/lib/objects/exception/no_node_found_for_breadcrumb.rb +8 -4
- data/lib/objects/exception/no_node_named_by_identifier.rb +8 -4
- data/lib/objects/exception/node_identifiers_must_be_unique.rb +8 -4
- data/lib/objects/exception/orchestration_script_does_not_exist.rb +8 -4
- data/lib/objects/exception/proxy_host_node_does_not_have_public_ip_address.rb +8 -4
- data/lib/objects/exception/unknown_dynamic_server_type.rb +11 -0
- data/lib/objects/exception/unknown_method_for_namespace.rb +8 -4
- data/lib/objects/exception/user_orchestration_error.rb +11 -0
- data/lib/objects/initialization/factory.rb +36 -0
- data/lib/objects/initialization/structure.rb +18 -0
- data/lib/objects/initialization/utils.rb +20 -0
- data/lib/objects/interactive/session.rb +4 -1
- data/lib/objects/interactive/session_item/base.rb +2 -0
- data/lib/objects/interactive/session_item/capture_input.rb +2 -0
- data/lib/objects/interactive/session_item/transparent_ssh.rb +29 -23
- data/lib/objects/loading_bar/handler.rb +80 -0
- data/lib/objects/loading_bar/indicator/base.rb +65 -0
- data/lib/objects/loading_bar/indicator/basic.rb +34 -0
- data/lib/objects/loading_bar/indicator/progress.rb +26 -0
- data/lib/objects/loading_bar/pid_bucket.rb +27 -0
- data/lib/objects/modules/context.rb +13 -9
- data/lib/objects/modules/draw.rb +49 -0
- data/lib/objects/modules/registry_management.rb +16 -10
- data/lib/objects/modules/tree.rb +157 -0
- data/lib/objects/modules/ui_output.rb +10 -6
- data/lib/objects/modules/workspace_commands.rb +131 -157
- data/lib/objects/modules/workspace_menu.rb +193 -123
- data/lib/objects/node/attributes.rb +17 -19
- data/lib/objects/node/base.rb +136 -74
- data/lib/objects/node/cache_handler.rb +3 -1
- data/lib/objects/node/collection.rb +10 -9
- data/lib/objects/node/factory.rb +47 -36
- data/lib/objects/node/inventory/base.rb +106 -100
- data/lib/objects/node/inventory/defined.rb +113 -89
- data/lib/objects/node/inventory/merge.rb +51 -0
- data/lib/objects/node/inventory/subselect.rb +66 -46
- data/lib/objects/node/kube/base.rb +51 -0
- data/lib/objects/node/kube/container.rb +9 -0
- data/lib/objects/node/kube/estate.rb +19 -0
- data/lib/objects/node/kube/namespace.rb +24 -0
- data/lib/objects/node/kube/pod.rb +24 -0
- data/lib/objects/node/kube_wrap.rb +26 -0
- data/lib/objects/node/meta/base.rb +8 -1
- data/lib/objects/node/meta/cloud.rb +2 -0
- data/lib/objects/node/meta/local.rb +2 -0
- data/lib/objects/node/meta_data_factory.rb +4 -2
- data/lib/objects/node/meta_data_loader.rb +28 -29
- data/lib/objects/node/resources/base.rb +5 -1
- data/lib/objects/node/resources/inventory.rb +26 -5
- data/lib/objects/node/resources/merged.rb +47 -0
- data/lib/objects/node/resources/sub_inventory.rb +12 -8
- data/lib/objects/node/server/base.rb +106 -71
- data/lib/objects/node/server/dynamic/base.rb +23 -0
- data/lib/objects/node/server/{dynamic.rb → dynamic/ec2.rb} +13 -13
- data/lib/objects/node/server/dynamic/gcp.rb +46 -0
- data/lib/objects/node/server/static.rb +34 -10
- data/lib/objects/orchestration/base.rb +17 -1
- data/lib/objects/orchestration/interactive_terraform.rb +59 -30
- data/lib/objects/orchestrator.rb +22 -0
- data/lib/objects/parser/bread_crumb.rb +3 -1
- data/lib/objects/registry/arguments/base.rb +3 -1
- data/lib/objects/registry/arguments/command_line.rb +6 -1
- data/lib/objects/registry/arguments/console.rb +4 -1
- data/lib/objects/registry/command/base.rb +3 -0
- data/lib/objects/registry/command/external.rb +9 -3
- data/lib/objects/registry/command/group.rb +11 -4
- data/lib/objects/registry/command/internal.rb +3 -1
- data/lib/objects/registry/command/shortcut.rb +17 -9
- data/lib/objects/registry/command_list.rb +2 -0
- data/lib/objects/registry/loader.rb +13 -10
- data/lib/objects/ssh/bootstrap.rb +3 -1
- data/lib/objects/ssh/command.rb +9 -8
- data/lib/objects/ssh/command_exec.rb +16 -10
- data/lib/objects/ssh/connection_wrangler.rb +122 -0
- data/lib/objects/ssh/connector.rb +108 -0
- data/lib/objects/ssh/driver.rb +28 -242
- data/lib/objects/ssh/driver_concerns/command_strings.rb +17 -0
- data/lib/objects/ssh/driver_concerns/connection.rb +70 -0
- data/lib/objects/ssh/driver_concerns/functions.rb +89 -0
- data/lib/objects/ssh/driver_concerns/user.rb +32 -0
- data/lib/objects/ssh/proxy_chain.rb +19 -0
- data/lib/objects/ssh/proxy_chain_link.rb +26 -0
- data/lib/objects/ssh/proxy_hop.rb +130 -0
- data/lib/objects/ssh/script_exec.rb +12 -11
- data/lib/objects/ssh/tunnel/local_port_forward.rb +5 -6
- data/lib/objects/ssh/tunnel_keeper.rb +21 -0
- data/lib/objects/ssh/window.rb +31 -0
- data/lib/objects/startup.rb +58 -0
- data/lib/objects/system/local.rb +3 -0
- data/lib/objects/terraform/output.rb +45 -0
- data/lib/objects/workspace.rb +13 -14
- data/patches/irb.rb +63 -6
- data/patches/string-encrypt.rb +20 -23
- data/patches/string.rb +18 -1
- data/patches/string_stylesheet.rb +2 -0
- metadata +157 -33
- data/lib/objects/driver/static.rb +0 -4
- data/lib/objects/progress_bar.rb +0 -30
- data/lib/objects/ssh/connection_handler.rb +0 -101
- data/lib/objects/ssh/proxy_data.rb +0 -56
- data/lib/objects/terraform/parser.rb +0 -23
- data/lib/objects/terraform/state.rb +0 -40
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bcome::Driver::Gcp::Authentication
|
4
|
+
class Base
|
5
|
+
include ::Bcome::LoadingBar::Handler
|
6
|
+
|
7
|
+
## Overrides
|
8
|
+
def authorized?
|
9
|
+
raise 'Should be overidden'
|
10
|
+
end
|
11
|
+
|
12
|
+
## Loading bar -
|
13
|
+
|
14
|
+
def loader_title
|
15
|
+
'Authenticating' + "\s#{@driver.pretty_provider_name.bc_blue.bold}\s#{@driver.pretty_resource_location.underline}".bc_green
|
16
|
+
end
|
17
|
+
|
18
|
+
## Credential helpers --
|
19
|
+
|
20
|
+
def credential_directory
|
21
|
+
'.gauth'
|
22
|
+
end
|
23
|
+
|
24
|
+
def full_path_to_credential_file
|
25
|
+
"#{credential_directory}/#{credential_file}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def credential_file
|
29
|
+
"#{@node.keyed_namespace}:#{credential_file_suffix}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def ensure_credential_directory
|
33
|
+
`mkdir -p #{credential_directory}`
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'google/api_client/auth/storage'
|
4
|
+
require 'google/api_client/auth/storages/file_store'
|
5
|
+
require 'google/api_client/client_secrets'
|
6
|
+
|
7
|
+
module Bcome::Driver::Gcp::Authentication
|
8
|
+
class Oauth < Base
|
9
|
+
include Utilities
|
10
|
+
|
11
|
+
credential_directory = '.gauth'
|
12
|
+
|
13
|
+
attr_reader :scopes, :secrets_filename, :service, :client_config
|
14
|
+
|
15
|
+
def initialize(driver, service, client_config, node)
|
16
|
+
@service = service
|
17
|
+
@scopes = client_config.scopes
|
18
|
+
@node = node
|
19
|
+
@driver = driver
|
20
|
+
@client_config = client_config
|
21
|
+
@secrets_filename = client_config.secrets_filename
|
22
|
+
@path_to_secrets = "#{credential_directory}/#{@secrets_filename}"
|
23
|
+
|
24
|
+
raise ::Bcome::Exception::Generic, "Missing OAuth 2.0 client secrets file from GCP network configuration. Cannot find '#{@path_to_secrets}'" unless File.exist?(@path_to_secrets) && File.file?(@path_to_secrets)
|
25
|
+
|
26
|
+
# All credentials are held in .gauth
|
27
|
+
ensure_credential_directory
|
28
|
+
end
|
29
|
+
|
30
|
+
def authorized?
|
31
|
+
storage && !@storage.authorization.nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def credential_file_suffix
|
35
|
+
'oauth2.json'
|
36
|
+
end
|
37
|
+
|
38
|
+
def authorize!
|
39
|
+
@service.authorization = storage.authorize
|
40
|
+
end
|
41
|
+
|
42
|
+
def client_secrets
|
43
|
+
@client_secrets ||= load_client_secrets
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_client_secrets
|
47
|
+
::Google::APIClient::ClientSecrets.load(@path_to_secrets)
|
48
|
+
rescue Exception => e
|
49
|
+
raise ::Bcome::Exception::MissingOrInvalidClientSecrets, "#{@path_to_secrets}. Gcp exception: #{e.class} #{e.message}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def storage
|
53
|
+
@storage ||= ::Google::APIClient::Storage.new(Google::APIClient::FileStore.new(full_path_to_credential_file))
|
54
|
+
end
|
55
|
+
|
56
|
+
def credential_file
|
57
|
+
# If an authorization has the same scopes & secrets file, it is the same authorization. Hence we store the resulting oauth2 access credentials as the same file. This allows
|
58
|
+
# re-use of authorizations and prevents multiple oauth loops.
|
59
|
+
"#{@client_config.checksum}:#{credential_file_suffix}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def do!
|
63
|
+
authorize!
|
64
|
+
if @storage.authorization.nil?
|
65
|
+
# Total bloat from google here. Thanks google... requiring at last possible moment.
|
66
|
+
require 'google/api_client/auth/installed_app'
|
67
|
+
|
68
|
+
wrap_indicator type: :basic, title: loader_title, completed_title: '' do
|
69
|
+
flow = Google::APIClient::InstalledAppFlow.new(
|
70
|
+
client_id: client_secrets.client_id,
|
71
|
+
client_secret: client_secrets.client_secret,
|
72
|
+
scope: @scopes
|
73
|
+
)
|
74
|
+
|
75
|
+
## Override the redirected-to screen so that clearer instruction can be given
|
76
|
+
flow.class.send(:remove_const,'RESPONSE_BODY') if flow.class.const_defined?('RESPONSE_BODY')
|
77
|
+
flow.class.send(:const_set,'RESPONSE_BODY', oauth_redirect_html)
|
78
|
+
|
79
|
+
begin
|
80
|
+
@service.authorization = flow.authorize(storage)
|
81
|
+
signal_success
|
82
|
+
rescue ArgumentError => e
|
83
|
+
signal_failure
|
84
|
+
raise ::Bcome::Exception::MissingOrInvalidClientSecrets, "#{@path_to_secrets}. Gcp exception: #{e.class} #{e.message}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
@service
|
90
|
+
end
|
91
|
+
|
92
|
+
def notify_success
|
93
|
+
print "[\s" + "Credentials file written to\s" + full_path_to_credential_file + "\s]" + "\n"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module Bcome::Driver::Gcp::Authentication
|
6
|
+
class OauthClientConfig
|
7
|
+
attr_reader :scopes, :secrets_filename
|
8
|
+
|
9
|
+
def initialize(scopes, secrets_filename)
|
10
|
+
@scopes = scopes
|
11
|
+
@secrets_filename = secrets_filename
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
checksum == other.checksum
|
16
|
+
end
|
17
|
+
|
18
|
+
def checksum
|
19
|
+
@checksum ||= ::Digest::MD5.hexdigest(Marshal.dump("#{@scopes}-#{@secrets_filename}"))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bcome::Driver::Gcp::Authentication
|
4
|
+
class OauthSessionStore
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@oauth_sessions = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def in_memory_session_for(oauth_client_config)
|
12
|
+
existing_session = @oauth_sessions.detect do |session|
|
13
|
+
session.client_config == oauth_client_config
|
14
|
+
end
|
15
|
+
existing_session
|
16
|
+
end
|
17
|
+
|
18
|
+
def <<(session)
|
19
|
+
@oauth_sessions << session
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bcome::Driver::Gcp::Authentication
|
4
|
+
class ServiceAccount < Base
|
5
|
+
def initialize(service, scopes, node, credentials_file_name, driver)
|
6
|
+
@service = service
|
7
|
+
@scopes = scopes
|
8
|
+
@node = node
|
9
|
+
@driver = driver
|
10
|
+
@credentials_file_name = credentials_file_name
|
11
|
+
ensure_credential_directory
|
12
|
+
ensure_credentials_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def do!
|
16
|
+
@service.authorization = service_account
|
17
|
+
end
|
18
|
+
|
19
|
+
def authorized?
|
20
|
+
!@service.authorization.nil?
|
21
|
+
end
|
22
|
+
|
23
|
+
def service_account
|
24
|
+
@service_account ||= ::Bcome::Driver::Gcp::Authentication::SignetServiceAccountClient.new(@scopes, credentials_file_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def credentials_file_path
|
28
|
+
has_namespaced_keyed_filename? ? namespaced_keyed_filename : defined_credentials_files
|
29
|
+
end
|
30
|
+
|
31
|
+
def ensure_credentials_file
|
32
|
+
return if has_namespaced_keyed_filename?
|
33
|
+
raise ::Bcome::Exception::MissingGcpServiceAccountCredentialsFilename unless @credentials_file_name
|
34
|
+
end
|
35
|
+
|
36
|
+
## New implementation - we take a defined file name for the service account credentials
|
37
|
+
## Clean & may be re-used
|
38
|
+
def defined_credentials_files
|
39
|
+
"#{credential_directory}/#{@credentials_file_name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def has_namespaced_keyed_filename?
|
43
|
+
@has_namespaced_keyed_filename ||= File.exist?(namespaced_keyed_filename)
|
44
|
+
end
|
45
|
+
|
46
|
+
## Older implementation - we infer the credentials file from the namespace
|
47
|
+
## Retained to provide backwards compatibility
|
48
|
+
def namespaced_keyed_filename
|
49
|
+
full_path_to_credential_file
|
50
|
+
end
|
51
|
+
|
52
|
+
def credential_file_suffix
|
53
|
+
'service-account.json'
|
54
|
+
end
|
55
|
+
#######################################
|
56
|
+
|
57
|
+
def authorize!
|
58
|
+
storage.authorize
|
59
|
+
@service.authorization = storage.authorization
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bcome::Driver::Gcp::Authentication
|
4
|
+
class SignetServiceAccountClient < Signet::OAuth2::Client
|
5
|
+
def initialize(scopes, service_account_json_path)
|
6
|
+
@scopes = scopes
|
7
|
+
@service_account_json_path = service_account_json_path
|
8
|
+
raise ::Bcome::Exception::GcpAuthServiceAccountMissingCredentials, @service_account_json_path unless File.exist?(@service_account_json_path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch_access_token(_options = {})
|
12
|
+
token = authorizer.fetch_access_token!
|
13
|
+
token
|
14
|
+
end
|
15
|
+
|
16
|
+
def authorize
|
17
|
+
@token ||= fetch_access_token
|
18
|
+
end
|
19
|
+
|
20
|
+
def authorizer
|
21
|
+
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
|
22
|
+
json_key_io: File.open(@service_account_json_path),
|
23
|
+
scope: @scopes
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Bcome::Driver::Gcp::Authentication::Utilities
|
2
|
+
|
3
|
+
def oauth_redirect_html
|
4
|
+
## [GR] Style rules: Explicitly no assets to be pulled from bcome remote (no tracking). Inline styles only.
|
5
|
+
## Made an exception for the google font, as the user is already oauthing against google in any case.
|
6
|
+
<<-HTML
|
7
|
+
<html>
|
8
|
+
<head>
|
9
|
+
<script>
|
10
|
+
function closeWindow() {
|
11
|
+
window.open('', '_self', '');
|
12
|
+
window.close();
|
13
|
+
}
|
14
|
+
setTimeout(closeWindow, 10);
|
15
|
+
</script>
|
16
|
+
</head>
|
17
|
+
<style>
|
18
|
+
@import url("https://fonts.googleapis.com/css2?family=Catamaran:wght@200;500&display=swap");
|
19
|
+
|
20
|
+
body {
|
21
|
+
font-family: 'Catamaran', sans-serif;
|
22
|
+
font-weight: 200;
|
23
|
+
color: #3E4E60;
|
24
|
+
}
|
25
|
+
</style>
|
26
|
+
<body>#{oauth_redirect_body}</body>
|
27
|
+
</html>
|
28
|
+
HTML
|
29
|
+
end
|
30
|
+
|
31
|
+
def oauth_redirect_body
|
32
|
+
<<-HTML
|
33
|
+
<p>
|
34
|
+
OAuth redirection for namespace <strong>#{@node.keyed_namespace}</strong> complete.
|
35
|
+
</p>
|
36
|
+
<p>
|
37
|
+
You may close this window and return to the Bcome Console.
|
38
|
+
</p>
|
39
|
+
HTML
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/objects/encryptor.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'diffy'
|
4
|
+
|
1
5
|
module Bcome
|
2
6
|
class Encryptor
|
3
|
-
|
4
|
-
|
5
|
-
|
7
|
+
UNENC_SIGNIFIER = ''
|
8
|
+
ENC_SIGNIFIER = 'enc'
|
9
|
+
AFFIRMATIVE = 'yes'
|
6
10
|
|
7
11
|
include Singleton
|
8
12
|
|
@@ -19,13 +23,23 @@ module Bcome
|
|
19
23
|
else
|
20
24
|
puts "\nNo unencrypted files to encrypt.\n".warning
|
21
25
|
end
|
22
|
-
|
26
|
+
nil
|
23
27
|
end
|
24
28
|
|
25
29
|
def prompt_for_key
|
26
|
-
|
30
|
+
puts "\n"
|
31
|
+
print 'Please enter an encryption key (and if your data is already encrypted, you must provide the same key): '.informational
|
27
32
|
@key = STDIN.noecho(&:gets).chomp
|
33
|
+
# puts "\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
def prompt_to_overwrite
|
37
|
+
valid_answers = [AFFIRMATIVE, 'no']
|
28
38
|
puts "\n"
|
39
|
+
print "Do you want to continue with unpacking this file? Your local changes would be overwritten [#{valid_answers.join(',')}]\s"
|
40
|
+
answer = STDIN.gets.chomp
|
41
|
+
prompt_to_overwrite unless valid_answers.include?(answer)
|
42
|
+
answer
|
29
43
|
end
|
30
44
|
|
31
45
|
def has_encrypted_files?
|
@@ -46,45 +60,117 @@ module Bcome
|
|
46
60
|
|
47
61
|
def unpack
|
48
62
|
prompt_for_key
|
49
|
-
toggle_packed_files(all_encrypted_filenames
|
50
|
-
|
63
|
+
toggle_packed_files(all_encrypted_filenames, :decrypt)
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def decrypt_file_data(filename)
|
68
|
+
raw_contents = File.read(filename)
|
69
|
+
raw_contents.send(:decrypt, @key)
|
70
|
+
end
|
71
|
+
|
72
|
+
def enc_file_diff(filename)
|
73
|
+
# Get decrypted file data
|
74
|
+
decrypted_data_for_filename = decrypt_file_data(filename)
|
75
|
+
|
76
|
+
# Get unpacked file data
|
77
|
+
opposing_filename = opposing_file_for_filename(filename)
|
78
|
+
return nil unless File.exist?(opposing_filename)
|
79
|
+
|
80
|
+
unpacked_file_data = File.read(opposing_filename)
|
81
|
+
|
82
|
+
# there are no differences
|
83
|
+
return nil if decrypted_data_for_filename.eql?(unpacked_file_data)
|
84
|
+
|
85
|
+
get_diffs(unpacked_file_data, decrypted_data_for_filename)
|
86
|
+
end
|
87
|
+
|
88
|
+
def opposing_file_for_filename(filename)
|
89
|
+
filename =~ %r{#{path_to_metadata}/(.+)\.enc}
|
90
|
+
"#{path_to_metadata}/#{Regexp.last_match(1)}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_diffs(file_one, file_two)
|
94
|
+
diffy = ::Diffy::SplitDiff.new(file_one, file_two)
|
95
|
+
left_diffs = diffy.left.split("\n").each_with_index.collect { |l, index| "#{index + 1}:\s#{l}" }
|
96
|
+
right_diffs = diffy.right.split("\n").each_with_index.collect { |l, index| "#{index + 1}:\s#{l}" }
|
97
|
+
|
98
|
+
diffed_lines = (left_diffs + right_diffs).select { |line| line =~ /^[0-9]+:\s[+-](.+)$/ }
|
99
|
+
return nil if diffed_lines.empty?
|
100
|
+
|
101
|
+
diffed_lines.collect do |line|
|
102
|
+
line =~ /^[0-9]+:\s\+(.+)$/ ? line.bc_green : line.bc_red
|
103
|
+
end.join("\n")
|
104
|
+
end
|
105
|
+
|
106
|
+
def diff
|
107
|
+
prompt_for_key
|
108
|
+
puts "\n"
|
109
|
+
all_encrypted_filenames.each do |filename|
|
110
|
+
opposing_file = opposing_file_for_filename(filename)
|
111
|
+
if File.exist?(opposing_file)
|
112
|
+
if diffs = enc_file_diff(filename)
|
113
|
+
puts "\n[+/-]\s".warning + filename + "\sis different to your local unpacked version\n\n"
|
114
|
+
puts diffs + "\n\n"
|
115
|
+
else
|
116
|
+
puts filename.to_s.informational + "\s- no differences".bc_green
|
117
|
+
end
|
118
|
+
else
|
119
|
+
puts filename.to_s.informational + "\s- new file".warning
|
120
|
+
end
|
121
|
+
end
|
122
|
+
puts "\n"
|
51
123
|
end
|
52
124
|
|
53
125
|
def toggle_packed_files(filenames, packer_method)
|
54
|
-
raise
|
126
|
+
raise 'Missing encryption key. Please set an encryption key' unless @key
|
127
|
+
|
55
128
|
filenames.each do |filename|
|
56
129
|
# Get raw
|
57
130
|
raw_contents = File.read(filename)
|
58
|
-
|
131
|
+
|
59
132
|
if packer_method == :decrypt
|
60
|
-
filename =~
|
61
|
-
opposing_filename =
|
62
|
-
action =
|
133
|
+
filename =~ %r{#{path_to_metadata}/(.+)\.enc}
|
134
|
+
opposing_filename = Regexp.last_match(1)
|
135
|
+
action = 'Unpacking'
|
136
|
+
|
137
|
+
# Skip unpacking a file if there are local modifications that the user does not want to lose.
|
138
|
+
if diffs = enc_file_diff(filename)
|
139
|
+
puts "\n[+/-]\s".warning + filename + "\sis different to your local unpacked version\n\n"
|
140
|
+
puts diffs
|
141
|
+
|
142
|
+
if prompt_to_overwrite != AFFIRMATIVE
|
143
|
+
puts "\n\nskipping\s".warning + filename + "\n"
|
144
|
+
next
|
145
|
+
end
|
146
|
+
puts "\n"
|
147
|
+
end
|
63
148
|
else
|
64
|
-
filename =~
|
65
|
-
opposing_filename = "#{
|
66
|
-
action =
|
67
|
-
end
|
149
|
+
filename =~ %r{#{path_to_metadata}/(.*)}
|
150
|
+
opposing_filename = "#{Regexp.last_match(1)}.enc"
|
151
|
+
action = 'Packing'
|
152
|
+
end
|
68
153
|
|
69
154
|
# Write encrypted/decryption action
|
70
155
|
enc_decrypt_result = raw_contents.send(packer_method, @key)
|
156
|
+
print "\n\n"
|
71
157
|
puts "#{action}\s".informational + filename + "\sto\s".informational + "#{path_to_metadata}/" + opposing_filename
|
72
158
|
write_file(opposing_filename, enc_decrypt_result)
|
73
159
|
end
|
74
160
|
puts "\ndone".informational
|
75
|
-
end
|
76
|
-
|
161
|
+
end
|
162
|
+
|
77
163
|
def path_to_metadata
|
78
|
-
|
164
|
+
'bcome/metadata'
|
79
165
|
end
|
80
166
|
|
81
167
|
def write_file(filename, contents)
|
82
168
|
filepath = "#{path_to_metadata}/#{filename}"
|
83
|
-
File.open(
|
169
|
+
File.open(filepath.to_s, 'w') { |f| f.write(contents) }
|
84
170
|
end
|
85
|
-
|
171
|
+
|
86
172
|
def all_unencrypted_filenames
|
87
|
-
Dir["#{metadata_path}/*"].reject {|f| f =~ /\.enc/}
|
173
|
+
Dir["#{metadata_path}/*"].reject { |f| f =~ /\.enc/ }
|
88
174
|
end
|
89
175
|
|
90
176
|
def all_encrypted_filenames
|
@@ -92,8 +178,7 @@ module Bcome
|
|
92
178
|
end
|
93
179
|
|
94
180
|
def metadata_path
|
95
|
-
|
181
|
+
'bcome/metadata'
|
96
182
|
end
|
97
|
-
|
98
183
|
end
|
99
184
|
end
|