|
1 | | -require 'faraday_middleware/aws_sigv4' |
| 1 | +require 'faraday_middleware/aws_sigv4' if ENV['AWS_OPENSEARCH'] == 'true' && ENV.fetch('AWS_AOSS', 'false') == 'false' |
| 2 | +require 'opensearch-aws-sigv4' |
| 3 | +require 'aws-sigv4' |
2 | 4 |
|
| 5 | +# Priority is given to AWS AOSS, then AWS OpenSearch, and finally vanilla OpenSearch |
3 | 6 | def configure_opensearch |
4 | | - if ENV['AWS_OPENSEARCH'] == 'true' |
| 7 | + if ENV['AWS_AOSS'] == 'true' |
| 8 | + aws_aoss_client |
| 9 | + elsif ENV['AWS_OPENSEARCH'] == 'true' |
5 | 10 | aws_os_client |
6 | 11 | else |
7 | 12 | os_client |
8 | 13 | end |
9 | 14 | end |
10 | 15 |
|
| 16 | +# os_client is used to connect to a standard OpenSearch cluster that does not require AWS SigV4 signing for |
| 17 | +# authentication. It creates a new OpenSearch::Client with logging enabled based on the OPENSEARCH_LOG |
| 18 | +# environment variable. |
| 19 | +# |
| 20 | +# @return [OpenSearch::Client] a client for connecting to a standard OpenSearch cluster |
| 21 | +# @note This is mostly used for connecting to a locally running OpenSearch instance |
11 | 22 | def os_client |
12 | 23 | OpenSearch::Client.new log: ENV.fetch('OPENSEARCH_LOG', false) |
13 | 24 | end |
14 | 25 |
|
| 26 | +# aws_os_client is used to connect to AWS OpenSearch Service which requires AWS SigV4 signing for authentication. It |
| 27 | +# creates a new OpenSearch::Client and configures it to use the aws_sigv4 middleware for request signing. The middleware |
| 28 | +# is configured with the AWS region, access key ID, secret access key, and optionally a session token if using temporary |
| 29 | +# credentials. The OPENSEARCH_URL environment variable is used to specify the endpoint of the OpenSearch cluster. |
| 30 | +# |
| 31 | +# @return [OpenSearch::Client] a client for connecting to AWS OpenSearch Service (ES) |
| 32 | +# @note This is the legacy method for this application and will be removed when we migrate to AOSS. |
| 33 | +# @note AWS OpenSearch Service can use long-lived access keys, unlike AWS AOSS which requires temporary credentials |
| 34 | +# obtained by assuming a role. |
15 | 35 | def aws_os_client |
16 | | - OpenSearch::Client.new log: ENV.fetch('OPENSEARCH_LOG', false), url: ENV['OPENSEARCH_URL'] do |config| |
| 36 | + OpenSearch::Client.new log: ENV.fetch('OPENSEARCH_LOG', false), url: ENV.fetch('OPENSEARCH_URL', nil) do |config| |
| 37 | + Rails.logger.debug "Configuring AWS OpenSearch Service client with URL: #{ENV.fetch('OPENSEARCH_URL', nil)}" |
17 | 38 | # personal keys use expiring credentials with tokens |
18 | 39 | if ENV['AWS_SESSION_TOKEN'].present? |
| 40 | + Rails.logger.debug "Using temporary credentials with session token" |
19 | 41 | config.request :aws_sigv4, |
20 | | - service: 'es', |
21 | | - region: ENV['AWS_REGION'], |
22 | | - access_key_id: ENV['AWS_ACCESS_KEY_ID'], |
23 | | - secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], |
24 | | - session_token: ENV['AWS_SESSION_TOKEN'] |
| 42 | + service: 'es', |
| 43 | + region: ENV.fetch('AWS_REGION', nil), |
| 44 | + access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID', nil), |
| 45 | + secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil), |
| 46 | + session_token: ENV['AWS_SESSION_TOKEN'] |
25 | 47 | # application keys don't use tokens |
26 | 48 | else |
| 49 | + Rails.logger.debug "Using long-lived credentials without session token" |
27 | 50 | config.request :aws_sigv4, |
28 | | - service: 'es', |
29 | | - region: ENV['AWS_REGION'], |
30 | | - access_key_id: ENV['AWS_ACCESS_KEY_ID'], |
31 | | - secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'] |
| 51 | + service: 'es', |
| 52 | + region: ENV.fetch('AWS_REGION', nil), |
| 53 | + access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID', nil), |
| 54 | + secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil) |
32 | 55 | end |
33 | 56 | end |
34 | 57 | end |
35 | 58 |
|
| 59 | +# aws_aoss_client is used to connect to AWS OpenSearch Serverless (AOSS) which has a different authentication mechanism |
| 60 | +# than AWS OpenSearch Service. It uses AWS SigV4 signing for authentication, and the OpenSearch::Aws::Sigv4Client is |
| 61 | +# specifically designed to handle this type of authentication. |
| 62 | +# |
| 63 | +# @return [OpenSearch::Aws::Sigv4Client] a client for connecting to AWS OpenSearch Serverless (AOSS) |
| 64 | +# @note this configuration uses temporary credentials obtained by assuming a role or via the AWS console, unlike |
| 65 | +# AWS OpenSearch Service which can use long-lived access keys directly. |
| 66 | +def aws_aoss_client |
| 67 | + Rails.logger.debug "Configuring AWS AOSS client with URL: #{ENV.fetch('OPENSEARCH_URL', nil)}" |
| 68 | + |
| 69 | + signer = Aws::Sigv4::Signer.new( |
| 70 | + service: 'aoss', |
| 71 | + region: ENV.fetch('AWS_REGION', nil), |
| 72 | + credentials_provider: credentials |
| 73 | + ) |
| 74 | + |
| 75 | + OpenSearch::Aws::Sigv4Client.new( |
| 76 | + { |
| 77 | + host: ENV.fetch('OPENSEARCH_URL', nil), |
| 78 | + log: true |
| 79 | + }, |
| 80 | + signer |
| 81 | + ) |
| 82 | +end |
| 83 | + |
| 84 | +def credentials |
| 85 | + if ENV.fetch('AWS_SESSION_TOKEN', false).present? |
| 86 | + Rails.logger.debug "Using temporary credentials with session token" |
| 87 | + temporary_credentials |
| 88 | + else |
| 89 | + Rails.logger.debug "Using long-lived credentials and assuming role" |
| 90 | + assume_role_credentials |
| 91 | + end |
| 92 | +end |
| 93 | + |
| 94 | +# personal keys use expiring credentials with tokens, so we use them directly without assuming a role |
| 95 | +# application keys use long-lived credentials and assume a role to get temporary credentials for AOSS |
| 96 | +def temporary_credentials |
| 97 | + Aws::Credentials.new( |
| 98 | + ENV.fetch('AWS_ACCESS_KEY_ID', nil), |
| 99 | + ENV.fetch('AWS_SECRET_ACCESS_KEY', nil), |
| 100 | + ENV.fetch('AWS_SESSION_TOKEN', nil) |
| 101 | + ) |
| 102 | +end |
| 103 | + |
| 104 | +# AWS AOSS uses temporary credentials that are obtained by assuming a role. The |
| 105 | +# Aws::AssumeRoleCredentials class is used to get these temporary credentials. It requires the ARN of |
| 106 | +# the role to assume, a session name, and a client for the AWS Security Token Service (STS) which is |
| 107 | +# used to perform the AssumeRole operation. It uses the AWS region and access keys from the |
| 108 | +# environment variables to create the STS client. When the session token expires, the |
| 109 | +# Aws::AssumeRoleCredentials will automatically refresh the credentials by calling AssumeRole again. |
| 110 | +def assume_role_credentials |
| 111 | + Aws::AssumeRoleCredentials.new( |
| 112 | + role_arn: ENV.fetch('AWS_AOSS_ROLE_ARN', nil), |
| 113 | + role_session_name: 'timdex-opensearch', |
| 114 | + client: Aws::STS::Client.new( |
| 115 | + region: ENV.fetch('AWS_REGION', nil), |
| 116 | + access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID', nil), |
| 117 | + secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY', nil) |
| 118 | + ) |
| 119 | + ) |
| 120 | +end |
| 121 | + |
36 | 122 | Timdex::OSClient = configure_opensearch |
0 commit comments