Sending IOS Push Notifications from Ruby On Rails - ios

I need to send push notifications to IOS mobile.
I used apn_on_rails for send this notifications.
I get my pem file from IOS developer.
I did the following configurations on it
In Productions & development in config/configtran/*.rb
RAILS_ROOT, APN::App::RAILS_ENV='production'
configatron.apn.passphrase = 'leo_123'
configatron.apn.port = 2195
configatron.apn.host = 'gateway.sandbox.push.apple.com'
configatron.apn.cert = File.join(Rails.root, 'config', ' apple_push_notification_development.pem')
And then i created one Notificationby following the documentation.
After i ran the following commands it stands ideal and responding
From console
APN::App.send_notifications
Using rake
RAILS_ENV=production rake apn:notifications:deliver
I tried that in both production and development environment.
After the follwing line it's not responding. I didn't found anything in Log also.
APN::App Load (0.1ms) SELECT "apn_apps".* FROM "apn_apps"
I haven't hosted this app in any cloud server. Is this application should host in any cloud server to work the app properly?
Any help appreciated.

It's easier to work with grocer gem.
pusher = Grocer.pusher(certificate: "#{Rails.root}/lib/dev_cert.pem", # required
passphrase: "XXXXXX", # optional
gateway: "gateway.sandbox.push.apple.com", # optional
port: 2195, #optional
retries: 3)
feedback = Grocer.feedback( certificate: "#{Rails.root}/lib/dev_cert.pem",
passphrase: "XXXXXX",
gateway: "feedback.sandbox.push.apple.com",
port: 2196,
retries: 3)
notification = Grocer::Notification.new(
device_token: push_id,
alert: message,
badge: 3,
sound: "siren.aiff", # optional
expiry: Time.now + 60*60, # optional; 0 is default, meaning the message is not stored
# identifier: 1234, # optional
content_available: true # optional; any truthy value will set 'content-available' to 1
)
feedback.each do |attempt|
puts "Device #{attempt.device_token} failed at #{attempt.timestamp}"
end
pusher.push(notification)

Related

Why is elasticserach-rails suddenly raising Faraday::ConnectionFailed (execution expired)?

I'm using Elasticsearch in a Rails app via the elasticsearch-model and elasticsearch-rails gems.
Everything was previously working fine, but after some updates I am now getting a Connection Failed error whenever I attempt to interact with the remote cluster (AWS Elasticsearch).
> MyModel.__elasticsearch__.create_index! force: true
=> Faraday::ConnectionFailed (execution expired)
I'm struggling to work out what is causing this connection error. After searching for similar issues, I've adjusted timeouts and tried various combinations of http, https and naked urls, but no success.
What is a sensible way to debug this connection error?
My Elasticsearch is initialized like this.
#initializers/elasticsearch.rb
require 'faraday_middleware'
require 'faraday_middleware/aws_sigv4'
credentials = Aws::Credentials.new(
ENV.fetch('AWS_ACCESS_KEY_ID'),
ENV.fetch('AWS_SECRET_ACCESS_KEY')
)
config = {
url: ENV.fetch('AWS_ELASTICSEARCH_URL'),
retry_on_failure: true,
transport_options: {
request: { timeout: 10 }
}
}
client = Elasticsearch::Client.new( config ) do |f|
f.request :aws_sigv4, credentials: credentials, service: 'es', region: ENV.fetch('AWS_ELASTICSEARCH_REGION')
end
Elasticsearch::Model.client = client
It turns out that there were two parts to this issue.
First, the Elasticsearch::Client, as configured above, was using the default ES port 9200. My ES is hosted on AWS, which appears to not expose this port.
After fixing this, I ran into the second issue (which I suspect is more specific to this app). I started getting a Faraday::ConnectionFailed (end of file) error. I don't know what caused this, but configuring the client with host and scheme fixed it.
My final config is as follows:
#initializers/elasticsearch.rb
# ...
config = {
host: ENV.fetch('AWS_ELASTICSEARCH_URL'),
port: 443,
scheme: "https",
retry_on_failure: true,
transport_options: {
request: { timeout: 10 }
}
}
client = Elasticsearch::Client.new( config ) do |f|
# ...
N.B. AWS_ELASTICSEARCH_URL must return a URL without protocol.
This is because of version issue.
Use this gem 'elasticsearch-model', '~> 5'

Ruby on rails: Hostname not found gateway.sandbox.push.apple.com

I'm working on a app where i use ruby on rails as server script. and my code was working fine but when i change the server. i get this error whenever i try to send a push notification.
Hostname not found: Gateway.sandbox.push.apple.com
and code pushcode:
pusher = Grocer.pusher(
certificate: "#{Rails.root}/public/PinkDev.pem", # required
#certificate: "#{Rails.root}/public/PinkDist.pem", # required
passphrase: 'xxxxxxx', # optional
#gateway: "gateway.push.apple.com", # optional; See note below.
gateway: "gateway.sandbox.push.apple.com", # sandbox.
port: 2195, # optional
retries: 3 # optional
)
notification = Grocer::Notification.new(
device_token: "#{device_token}",
alert: "#{alert}",
sound: "default",
content_available: true,
badge:count,
custom: {
"others": {:device_token =>xxxxx,:access_token=>xxxxx, :alert=>xxxx,:push_type=>xxxx,:xxxxx=> xxx,:xxxx=>xxxx, :user_id=>xxxx, :badge=>xxxxx}}
)
pusher.push(notification)
how can i resolve this issue?

Faraday::SSLError for Elasticsearch

Currently running into an issue where my background workers which are communicating with elasticsearch via elasticsearch-client are running into SSL errors inside Faraday.
The error is this:
SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: sslv3 alert handshake failure
The configuration works fine some of the time (around ~50%) and it has never failed for me inside of a console sessions.
The trace of the command is this:
curl -X GET 'https://<host>/_alias/models_write?pretty
The client config is this
Thread.current[:chewy_client] ||= begin
client_configuration[:reload_on_failure] = true
client_configuration[:reload_connections] = 30
client_configuration[:sniffer_timeout] = 0.5
client_configuration[:transport_options] ||= {}
client_configuration[:transport_options][:ssl] = { :version => :TLSv1_2 }
client_configuration[:transport_options][:headers] = { content_type: 'application/json' }
client_configuration[:trace] = true
client_configuration[:logger] = Rails.logger
::Elasticsearch::Client.new(client_configuration) do |f|
f.request :aws_signers_v4,
credentials: AWS::Core::CredentialProviders::DefaultProvider.new,
service_name: 'es',
region: ENV['ES_REGION'] || 'us-west-2'
end
end
As you can see I explicitly set the ssl version to TSLv1_2, but still getting an SSLv3 error.
Thought maybe it was a race condition issue. So ran a script spawning about 10 processes with 50 threads each and calling the sidekiq perform method inside and still not able to reproduce.
I am using the managed AWS 2.3 Elasticsearch if that is at all relevant.
Any help or guidance in the right direction would be greatly appreciated, I would be happy to attach as much info as needed.
Figured it out. The problem was that the elasticsearch-ruby gem autoloads in an http adapter that it detects if one is not specified. The one used in my console was not the one getting auto loaded into sidekiq.
The sidekiq job was using the HTTPClient adapter which did not respect the SSL version option. Thus I was getting this error. After explicitly defining the faraday adapter it worked.

ActionMailer SMTP "certificate verify failed"

I want to send emails from my Rails web application, and I do not want to disable TLS certificate verification. However for some reason, it always fails with "SSLv3 read server certificate B: certificate verify failed", even though the server certificate is valid.
I doubled checked with openssl s_client (using /etc/ssl/certs/ca-certificates.crt), and running the following in the rails console also works, delivering successfully.
smtp = Net::SMTP.new(host, port)
smtp.enable_tls
smtp.start("localhost", username, password, :login) do |smtp|
smtp.send_message msgstr, from, to
end
The server has Rails 4.2.6 and Ruby 2.3.0
config.action_mailer.smtp_setting = {
address:
port: 465,
user_name:
password:
authentication: :login,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
enable_starttls_auto: false,
ssl: true
}
From the described behavior I am quite sure that peer verification has not been done in the console and that you need to explicitly set the certificate store for verifying peer certificates in your Rails configuration.
Why it "works" in the console and how to actually verify peers there:
The observation that it works from the console but does not from Rails code is caused by the fact that smtp.enable_tls in your console code does not force peer verification whereas your Rails configuration apparently does. Indeed, when you write the command to the console, you get the SSLContext printed out:
smtp.enable_tls
# => #<OpenSSL::SSL::SSLContext:0x000000064043d0 #cert=nil, #key=nil,
#client_ca=nil, #ca_file=nil, #ca_path=nil, #timeout=nil,
#verify_mode=nil, #verify_depth=nil, #renegotiation_cb=nil,
#verify_callback=nil, #cert_store=nil, #extra_chain_cert=nil,
#client_cert_cb=nil, #session_id_context=nil, #tmp_dh_callback=nil,
#session_get_cb=nil, #session_new_cb=nil, #session_remove_cb=nil,
#tmp_ecdh_callback=nil, #servername_cb=nil, #npn_protocols=nil,
#alpn_protocols=nil, #alpn_select_cb=nil, #npn_select_cb=nil>
Note that #verify_mode is nil so there is no peer verification enabled by default on the SSLContext.
To force peer verification in console, so that you can play with the SSL settings manually, you need to use a custom SSLContext and pass it to enable_tls:
ssl_context = Net::SMTP.default_ssl_context
ssl_context.set_params
smtp.enable_tls(ssl_context)
# => #<OpenSSL::SSL::SSLContext:0x000000063c27c8 #cert=nil, #key=nil,
#client_ca=nil, #ca_file=nil, #ca_path=nil, #timeout=nil,
#verify_mode=1, #verify_depth=nil, #renegotiation_cb=nil,
#verify_callback=nil, #cert_store=#<OpenSSL::X509::Store:0x00000002894408 #verify_callback=nil, #error=nil, #error_string=nil, #chain=nil, #time=nil>, #extra_chain_cert=nil,
#client_cert_cb=nil, #session_id_context=nil, #tmp_dh_callback=nil,
#session_get_cb=nil, #session_new_cb=nil, #session_remove_cb=nil,
#tmp_ecdh_callback=nil, #servername_cb=nil, #npn_protocols=nil,
#alpn_protocols=nil, #alpn_select_cb=nil, #npn_select_cb=nil>
Watch closely the differences: the SSLContext now has verify_mode set to 1 and has a certificate store for the verifications defined. This is (among other things) what the set_params method in SSLContext does.
How to configure the certificate store in Rails
Now, Rails does not call the set_params methods when constructing the SSLContext for SMTP connection. Instead, it sets the individual attributes on it according to the options (see here and here in the source code). You have properly configured Rails that you want to verify peer certificates but you have not configured a certificate store to verify peers against.
This can be done using the ca_file or ca_path options, so the following Rails configuration should work for you:
config.action_mailer.smtp_setting = {
...
ssl: true
enable_starttls_auto: false,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}
I have no idea why this is not properly documented in the Rails Guides...
This Rails configuration works for me (using Ruby 2.2.2 and Rails 5):
ActionMailer::Base.smtp_setting = {
...
enable_starttls_auto: true,
openssl_verify_mode: OpenSSL::SSL::VERIFY_PEER,
openssl_verify_depth: 3, # if your CA is a sub signer
ca_file: "/etc/ssl/certs/ca-certificates.crt",
...
}

Gitlab LDAP (Active Directory) Authentication without Server Side Access

I am using GitLab Omnibus 7.10.0 on RHEL 6.6. I have enabled LDAP using the following configuration:
gitlab_rails['ldap_enabled'] = true
gitlab_rails['ldap_servers'] = YAML.load <<-'EOS' # remember to close this block with 'EOS' below
main: # 'main' is the GitLab 'provider ID' of this LDAP server
label: 'FOO COM Active Directory (LDAP)'
host: 'ad.server.foo.com'
port: 3268
uid: 'someuser'
method: 'plain' # "tls" or "ssl" or "plain"
bind_dn: 'CN=My Whole. Name,OU=Some Users,DC=ad,DC=server,DC=foo,DC=com'
password: 'thepassword'
active_directory: true
allow_username_or_email_login: false
block_auto_created_users: false
base: 'DC=ad,DC=server,DC=foo,DC=com'
user_filter: ''
# ## EE only
# group_base: ''
# admin_group: ''
# sync_ssh_keys: false
#
# secondary: # NOT FILLED OUT
EOS
My problem is that I can't get users to authenticate via LDAP. I'm not sure if the configuration is wrong, or I need to do something on the server side (which I have no direct access to). When I run
gitlab-rake gitlab:ldap:check RAILS_ENV=production
I get this
Checking LDAP ...
LDAP users with access to your GitLab server (only showing the first 100 results)
Server: ldapmain
Checking LDAP ... Finished
I can search for individual users using java with this account (my personal account) or another account for a different application, but can't get AD working with gitlab. I got the bind_dn "My Whole. Name" by running this command on a Windows box.
gpresult -r
I have also tried a bind_dn of:
uid=myADaccountname,OU=Some Users,DC=ad,DC=server,DC=foo,DC=com
and
myADaccountname#ad.server.foo.com
but I still have the same problem.
For Active Directory, the uid should be:
uid: 'sAMAccountName'
Gitlab should connect using the user specified in the bind_dn, with the given password.
Since GitLab 9.5.1 the uid now requires [ ]
See this issue: https://gitlab.com/gitlab-org/gitlab-ce/issues/37120
This might just be a bug which will be fixed.
I had to update the value for Active Directory from the answer above to:
uid: ['sAMAccountName']

Resources