Making Comeonin's hashpwsalt() deterministic (Phoenix) - authentication

In my Phoenix project, I am using:
{:comeonin, "~> 4.0"},
{:bcrypt_elixir, "~> 0.12.0"},
I see a lot of examples of user creation/authentication in which Comeonin.Bcrypt.hashpwsalt(password) is called with one argument. However, when I run this, or add_hash() from iex, it seems like the outputs are indeterministic:
iex(10)> password = Comeonin.Bcrypt.hashpwsalt("password")
"$2b$12$QUL1ytej8UqTvpU34E2oieshgOonf0RRZI0nva6T3HlK2RQ2JT74O"
iex(11)> password = Comeonin.Bcrypt.hashpwsalt("password")
"$2b$12$jz3sb5rLrmdHVRr7Nvq0te9He0Wt00DYy4kM.t9LFp6ZSx.siovJC"
iex(12)> password = Comeonin.Bcrypt.add_hash("password")
%{password: nil,
password_hash: "$2b$12$4Ih30p4LbNk5LQStMDtah.ht0AQSO8mhhfCUeRQlFSNuI9vEgKI/q"}
iex(13)> password = Comeonin.Bcrypt.add_hash("password")
%{password: nil,
password_hash: "$2b$12$92oe9Ccovrwi1GuHK5Zo3uaxbQEXEvgyqEx6o4tsW2J8TEsc/LrtS"}
Why does this occur, and how can I guarantee a deterministic hash from a given input?

hashpwsalt generates a random salt each time, so the resulting hash is going to be different every time. This is the recommended way of generating a password hash. You then use check_pass or checkpw for checking if a password matches the stored hash. If for some reason you want to get the same hash, you can use the library directly. For an example, see here:
https://github.com/riverrun/bcrypt_elixir/blob/master/lib/bcrypt.ex#L84
Can't think of a reason you would want to do this, though. It's more likely that you're making a mistake.

Related

Enable Impala Impersonation on Superset

Is there a way to make the logged user (on superset) to make the queries on impala?
I tried to enable the "Impersonate the logged on user" option on Databases but with no success because all the queries run on impala with superset user.
I'm trying to achieve the same! This will not completely answer this question since it does not still work but I want to share my research in order to maybe help another soul that is trying to use this instrument outside very basic use cases.
I went deep in the code and I found out that impersonation is not implemented for Impala. So you cannot achieve this from the UI. I found out this PR https://github.com/apache/superset/pull/4699 that for whatever reason was never merged into the codebase and tried to copy&paste code in my Superset version (1.1.0) but it didn't work. Adding some logs I can see that the configuration with the impersonation is updated, but then the actual Impala query is with the user I used to start the process.
As you can imagine, I am a complete noob at this. However I found out that the impersonation thing happens when you create a cursor and there is a constructor parameter in which you can pass the impersonation configuration.
I managed to correctly (at least to my understanding) implement impersonation for the SQL lab part.
In the sql_lab.py class you have to add in the execute_sql_statements method the following lines
with closing(engine.raw_connection()) as conn:
# closing the connection closes the cursor as well
cursor = conn.cursor(**database.cursor_kwargs)
where cursor_kwargs is defined in db_engine_specs/impala.py as the following
#classmethod
def get_configuration_for_impersonation(cls, uri, impersonate_user, username):
logger.info(
'Passing Impala execution_options.cursor_configuration for impersonation')
return {'execution_options': {
'cursor_configuration': {'impala.doas.user': username}}}
#classmethod
def get_cursor_configuration_for_impersonation(cls, uri, impersonate_user,
username):
logger.debug('Passing Impala cursor configuration for impersonation')
return {'configuration': {'impala.doas.user': username}}
Finally, in models/core.py you have to add the following bit in the get_sqla_engine def
params = extra.get("engine_params", {}) # that was already there just for you to find out the line
self.cursor_kwargs = self.db_engine_spec.get_cursor_configuration_for_impersonation(
str(url), self.impersonate_user, effective_username) # this is the line I added
...
params.update(self.get_encrypted_extra()) # already there
#new stuff
configuration = {}
configuration.update(
self.db_engine_spec.get_configuration_for_impersonation(
str(url),
self.impersonate_user,
effective_username))
if configuration:
params.update(configuration)
As you can see I just shamelessy pasted the code from the PR. However this kind of works only for the SQL lab as I already said. For the dashboards there is an entirely different way of querying Impala that I did not still find out.
This means that queries for the dashboards are handled in a different way and there isn't something like this
with closing(engine.raw_connection()) as conn:
# closing the connection closes the cursor as well
cursor = conn.cursor(**database.cursor_kwargs)
My gut (and debugging) feeling is that you need to first understand the sqlalchemy part and extend a new ImpalaEngine class that uses a custom cursor with the impersonation conf. Or something like that, however it is not simple (if we want to call this simple) as the sql_lab part. So, the trick is to find out where the query is executed and create a cursor with the impersonation configuration. Easy, isnt'it ?
I hope that this could shed some light to you and the others that have this issue. Let me know if you did find out another way to solve this issue, or if this comment was useful.
Update: something really useful
A colleague of mine succesfully implemented impersonation with impala without touching any superset related, but instead working directly with the impyla lib. A PR was open with the code to change. You can apply the patch directly in the impyla src used by superset. You have to edit both dbapi.py and hiveserver2.py.
As a reminder: we are still testing this and we do not know if it works with different accounts using the same superset instance.

Require one state or another state with salt

I'm looking since several hours for a technic to write a salt state wich requires requirement1 or requirement2.
That's what I would like to do with cmd.run for example:
Run myscript:
cmd.run:
- name: /path/to/myscript
- require:
- pkgs: pkg1|pkg2
- cwd: /
Which means The script my_script will be executed if the state installing the package pkg1 or the state installing the pkg2 is satisfied.
Can this be really be done with salt? If so how?
I know I can make all my checks in my script directly, but I wanted to know if salt requisites could do that cleverly.
Thanks.
Salt states do not support branching if/else/while/ etc. The states file redered into a data which describes static dependency trees. Once rendered, the execution is performed in order.
The only way to do some sort of branching is to use unless/onlyif keywords. But they only work with specific state types and do not accept state ids (AFAIK, they only accept executable shell commands). See: http://docs.saltstack.com/en/latest/ref/states/requisites.html#unless

Rails 3: How to get external ruby script output

I'm doing an online-judge application and I wish to run a ruby script (or a c++, java, etc program) from a controller, save the output in a variable and compare it to a test file I have in my database.
I'm stuck with running the program and checking the answer it sends to standard output. I've tried answer = load path, (being "path" a variable with the path of the script) but that returns "true" instead of the stdout content; and answer = `ruby path` but it doesn't recognize the path variable.
Thanks for your time in advance.
Try this: system("ruby #{path}"), but be careful not to pass any user-submitted information to the path variable (or at least sanitize it thoroughly), as this can pose extremely serious security risk.

undefined method 'path' for nil:NilClass using chargify_api_ares gem

I feel like this should be a simple problem, but I'm pulling my hair out trying to track it down. I'm installed the chargify_api_ares gem, but can't do even basic things such as
Chargify::Subscription.create
As I get this path error. I feel like this must be a gem issue somehow but don't know where to go from here.
UPDATE: bundle show chargify_api_ares shows the correct path, I just somehow can't access it. Still trying random environment related things.
Looks like this is the source of the problem, in active_resource\base.rb:
# Gets the \prefix for a resource's nested URL (e.g., <tt>prefix/collectionname/1.json</tt>)
# This method is regenerated at runtime based on what the \prefix is set to.
def prefix(options={})
default = site.path
default << '/' unless default[-1..-1] == '/'
# generate the actual method based on the current site path
self.prefix = default
prefix(options)
end
As I understand it, Chargify.subdomain should be setting the site.path, but I don't understand activeresource well enough yet to know what's happening and will continue to dig.
I too had the same issue.
I executed the following on the console
Chargify.configure do |c|
c.api_key = "<<api_key>>"
c.subdomain = "<<subdomain>>"
end
After that performing any Chargify console commands went through fine.

Ruby 1.9: gem crypt19 : blowfish.encrypt_string : problem with encoding

I am building a Rails app where I serialize a hash to JSON, and then encode the hash using the gem crypt19 and the blowfish algorithm. I'm using Rails 3.0.9, Ruby 1.9.2 p180, the latest crypt19 v1.2.1 and I'm developing on Windows7. In my Rails controller, I do:
require 'crypt/blowfish'
h=Hash.new
h["thing"]="12345"
h["thang"]="abcdefghijklmnopqrstuvwxyz"
blowfish=Crypt::Blowfish.new("SECRET")
encrypted_thingy=blowfish.encrypt_string(h.to_json)
I assign encrypted_thingy to a value in the model (which is a string),
#my_model.string_thing=encrypted_thingy
#my_model.save
but when I save the model it throws an Argument Error exception where the model is saved.
invalid byte sequence in US-ASCII
(And when I assign it a plain old string, #my_model="xxxxxxxx", everything works fine.
My eventual plan is to store encrypted_thingy in the database via the model, and then later decrypt it, parse out JSON, and get the values for "thing" and "thang".
Searching the 'net suggested that I need to change the encoding, but it is not clear how I do that with the result of the crypt19/blowfish encoding.
Is there any way to store this encrypted string as a string just like any other string I store?
Or is there a way to apply some magic (along with reversible magic) to turn that funky string into a real string which I can pass around in an email?
I was able to make it work. There is a gem called "hex_string" which converts binary-ish things with strange encodings into byte strings.
First I had to do
gem install hex_string
Then the code looked like this
require 'crypt/blowfish'
require 'hex_string'
h=Hash.new
h["thing"]="12345"
h["thang"]="abcdefghijklmnopqrstuvwxyz"
blowfish=Crypt::Blowfish.new("SECRET")
encrypted_thingy=blowfish.encrypt_string(h.to_json).to_hex_string.split(" ").join
The "encrypted_thingy" was now a string which I could pass around easily in my web app, store in a database, debug, etc without worrying about character encoding, etc.
To reverse the process, I did this:
decrypted_string= blowfish.decrypt_string(encrypted_thingy.to_byte_string)
The decrypted string could then be JSON-parsed to extract the data in the original hash.