Coder Social home page Coder Social logo

nerves_hub_cli's People

Contributors

brianberlin avatar connorrigby avatar danielspofford avatar dependabot[bot] avatar fhunleth avatar jjcarstens avatar joshk avatar mobileoverlord avatar oestrich avatar pcmarks avatar pdgonzalez872 avatar pojiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nerves_hub_cli's Issues

Local certificate password should be referred to as pass-phrase

This was brought up during the conference training at ElixirConf EU 2019 in Prague.

There was a bit of trouble with confusion around the password for the account and the password for the certificate. People mix them up and most people are familiar with the difference in terminology between password (for an account) and pass-phrase (for an encryption key).

Justin (@mobileoverlord) wanted an issue about. So here we are.

Allow retry on a failed password

Currently you're asked once for your password and if you mess it up, you need to start over again. It seems like we should be nicer and allow for three attempts.

Also see #76.

nerves_hub.device list fails with no devices

Using mix nerves_hub.device list for an org that has no devices fails on the command line. It might be better to handle it more gently with a specific message so don't freak out at the error.

jonjon@ ๐Ÿ“‚ {nerves_hub_cli} $ mix nerves_hub.device list
NervesHub server: api.nerves-hub.org:443
NervesHub organization: jonjon
Local NervesHub user password: 
** (TableRex.Error) Table must have at least one row before being rendered
    (table_rex) lib/table_rex.ex:28: TableRex.quick_render!/3
    (nerves_hub_cli) lib/mix/tasks/nerves_hub.device.ex:155: Mix.Tasks.NervesHub.Device.list/2
    (mix) lib/mix/task.ex:331: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2

nerves_hub.deployement create should quote deployment name in example text.

nerves_team_device $ mix nerves_hub.deployment update Test 1 is_active true
NervesHub server: api.nerves-hub.org:443
NervesHub organization: aselder
** (Mix) Invalid arguments to mix nerves_hub.deployment.

Usage:
mix nerves_hub.deployment list
mix nerves_hub.deployment create
mix nerves_hub.deployment update DEPLOYMENT_NAME KEY VALUE

Run mix help nerves_hub.deployment for more information.

Uploading unsigned firmware raises error

** (Protocol.UndefinedError) protocol Enumerable not implemented for "invalid_signature"
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:141: Enumerable.reduce/3
    (elixir) lib/enum.ex:2979: Enum.reduce/3
    (nerves_hub_cli) lib/mix/nerves_hub/shell.ex:90: Mix.NervesHubCLI.Shell.render_error/1
    (mix) lib/mix/task.ex:316: Mix.Task.run_task/3
    (mix) lib/mix/cli.ex:79: Mix.CLI.run_task/2

Allow suplying org from `config.exs`

According to the docs on nerves_hub if one doesn't use the default org created with Nerves-Hub

config :nerves_hub,
  public_keys: [:prod, :staging, :"staging-2"]

You get a error:

== Compilation error in file lib/nerves_hub/certificate.ex ==
** (Mix.Error) NervesHub is unable to find key: :prod
    (mix) lib/mix.ex:323: Mix.raise/1
    lib/nerves_hub_cli.ex:27: anonymous fn/3 in NervesHubCLI.public_keys/1
    (elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
    lib/nerves_hub/certificate.ex:3: (module)

Import previously created signing keys

It would be useful to be able to import keys that have already been created with fwup -g.

Maybe something like:

mix nerves_hub.key import NAME PUBLIC_KEY_FILE PRIVATE_KEY_FILE

Silent failure in `mix firmware`

Hello from the workshop!

I just put invalid stuff like

config :nerves_hub,                                                                                   |~                                                                                                        
  fwup_public_keys: ["supersecret"]                                                                                        

into rel/config.exs instead of config/config.exs.

mix firmware aborted with some exit status, but bare any error message:

> mix firmware 

Nerves environment
  MIX_TARGET:   rpi0
  MIX_ENV:      dev

|nerves_bootstrap| Building OTP Release...

โœ˜ # exit status != 0 in my shell prompt

importing an existing firmware signing key fails

if you upload or create a key, and then export it to give to someone else, and try to import it, it will succeed, but give an error from the API when trying to upload it to nerves-hub

Unhandled error: {:error, %{"errors" => %{"name" => ["has already been taken"]}}}

Do not ask for "Local NervesHub user password" for every command

Problem

For every mix nerves_hub.* command, I have to enter my Local NervesHub user password.

I gather this is the passphrase for my local user certificate.

Can I avoid this?

Ideas

  1. Add passphrase to macos keychain (how?)
  2. Generate user certificate without a passphrase (how?)

Workaround

mix nerves_hub.user cert export
cd ~/nerves-hub/
tar -xvzf ./nerves_hub-certs.tar.gz
export NERVES_HUB_CERT=`cat ./cert.pem`
export NERVES_HUB_KEY=`cat ./key.pem`

Key/Cert export tasks broken

It seems the directory structure changed, and this task now fails:

mix nerves_hub.key export prod --org farmbot-production
NervesHub server: api.nerves-hub.org:443
NervesHub organization: farmbot-production
Local signing key password for 'prod':  
Unhandled error: {:error, "Couldn't find /home/connor/.nerves-hub/keys/farmbot-production/prod.pub or /home/connor/.nerves-hub/keys/farmbot-production/prod.priv"}

Deleting a firmware signing key that has associations produces large error

We need to capture constraint errors and present them in a pretty way.

Deleting remote signing key test
Unhandled error: {:error, {:error, %Jason.DecodeError{data: "# Ecto.ConstraintError at DELETE /orgs/nerveshub/keys/test\n\nException:\n\n    ** (Ecto.ConstraintError) constraint error when attempting to delete struct:\n    \n        * foreign_key: firmwares_tenant_key_id_fkey\n    \n    If you would like to convert this constraint into an error, please\n    call foreign_key_constraint/3 in your changeset and define the proper\n    constraint name. The changeset has not defined any constraint.\n    \n        (ecto) lib/ecto/repo/schema.ex:574: anonymous fn/4 in Ecto.Repo.Schema.constraints_to_errors/3\n        (elixir) lib/enum.ex:1314: Enum.\"-map/2-lists^map/1-0-\"/2\n        (ecto) lib/ecto/repo/schema.ex:559: Ecto.Repo.Schema.constraints_to_errors/3\n        (ecto) lib/ecto/repo/schema.ex:386: anonymous fn/9 in Ecto.Repo.Schema.do_delete/4\n        (ecto) lib/ecto/repo/schema.ex:774: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6\n        (ecto) lib/ecto/adapters/sql.ex:576: anonymous fn/3 in Ecto.Adapters.SQL.do_transaction/3\n        (db_connection) lib/db_connection.ex:1283: DBConnection.transaction_run/4\n        (db_connection) lib/db_connection.ex:1207: DBConnection.run_begin/3\n        (db_connection) lib/db_connection.ex:798: DBConnection.transaction/3\n        (nerves_hub_api) lib/nerves_hub_api_web/controllers/key_controller.ex:34: NervesHubAPIWeb.KeyController.delete/2\n        (nerves_hub_api) lib/nerves_hub_api_web/controllers/key_controller.ex:1: NervesHubAPIWeb.KeyController.action/2\n        (nerves_hub_api) lib/nerves_hub_api_web/controllers/key_controller.ex:1: NervesHubAPIWeb.KeyController.phoenix_controller_pipeline/2\n        (nerves_hub_api) lib/nerves_hub_api_web/endpoint.ex:1: NervesHubAPIWeb.Endpoint.instrument/4\n        (phoenix) lib/phoenix/router.ex:275: Phoenix.Router.__call__/1\n        (nerves_hub_api) lib/nerves_hub_api_web/endpoint.ex:1: NervesHubAPIWeb.Endpoint.plug_builder_call/2\n        (nerves_hub_api) lib/plug/debugger.ex:122: NervesHubAPIWeb.Endpoint.\"call (overridable 3)\"/2\n        (nerves_hub_api) lib/nerves_hub_api_web/endpoint.ex:1: NervesHubAPIWeb.Endpoint.call/2\n        (phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:33: Phoenix.Endpoint.Cowboy2Handler.init/2\n        (cowboy) /Users/jschneck/Developer/nerves/nerves_hub_web/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2\n        (cowboy) /Users/jschneck/Developer/nerves/nerves_hub_web/deps/cowboy/src/cowboy_stream_h.erl:274: :cowboy_stream_h.execute/3\n    \n\n## Connection details\n\n### Params\n\n    %{\"name\" => \"test\", \"org_name\" => \"nerveshub\"}\n\n### Request info\n\n  * URI: https://0.0.0.0:4002/orgs/nerveshub/keys/test\n  * Query string: \n\n### Headers\n  \n  * content-type: application/json\n  * host: 0.0.0.0:4002\n  * user-agent: hackney/1.13.0\n\n### Session\n\n    %{}\n", position: 0, token: nil}}}

Support bulk device registration via a CSV file

I have >1000 devices to add to NervesHub and it would be really convenient if nerves_hub_cli could take a file that has information for all of the devices.

I have a list of serial numbers from the factory and some information. I can write a program to convert that list to any format that makes sense for nerves_hub_cli.

I'm open to any format that's not too hard to generate, but how about a .csv file with the following columns:

serial number, "list of tags separated by commas and surrounded by double quotes", description

Help text is not discoverable

After a while of not using nerves_hub, it's not particularly easy to find the command for certain things. It would be nice if mix help nerves_hub listed all the available tasks and how to get more help for each of them

user.auth ArgumentError

Generated demo_fw app
NervesHub server: nerveshub.fly.dev:443
Username or email address: connorrigby
NervesHub password: 
Authenticating...
** (ArgumentError) errors were found at the given arguments:

  * 1st argument: not a binary

    :erlang.binary_to_atom(nil, :utf8)
    (tesla 1.8.0) lib/tesla/adapter/mint.ex:161: Tesla.Adapter.Mint.open_conn/2
    (tesla 1.8.0) lib/tesla/adapter/mint.ex:121: Tesla.Adapter.Mint.do_request/5
    (tesla 1.8.0) lib/tesla/adapter/mint.ex:61: Tesla.Adapter.Mint.call/2
    (tesla 1.8.0) lib/tesla/middleware/json.ex:57: Tesla.Middleware.JSON.call/3
    (tesla 1.8.0) lib/tesla/middleware/follow_redirects.ex:46: Tesla.Middleware.FollowRedirects.redirect/3
    (nerves_hub_cli 2.0.0) lib/nerves_hub_cli/api.ex:42: NervesHubCLI.API.request/4
    (nerves_hub_cli 2.0.0) lib/mix/tasks/nerves_hub.user.ex:108: Mix.Tasks.NervesHub.User.auth/1

This happens when using the official docs here

Can't create certificate using env vars

$ echo $NERVES_HUB_CERT
-----BEGIN CERTIFICATE-----
MIIB4jCCA <SNIP>
-----END CERTIFICATE-----

$ echo $NERVES_HUB_KEY
g3QAAAAFZAAKYP <SNIP>

$ mix nerves_hub.device cert create West100      

Nerves environment
  MIX_TARGET:   print_server_rpi3
  MIX_ENV:      dev

NervesHub server: api.nerves-hub.org:443
NervesHub organization: crowdcow
Creating certificate for West100
** (MatchError) no match of right hand side value: {:error, :not_found}
    (x509 0.8.1) lib/x509/private_key.ex:215: X509.PrivateKey.from_pem!/2
    (nerves_hub_cli 0.9.1) lib/mix/nerves_hub/shell.ex:40: Mix.NervesHubCLI.Shell.request_auth/1
    (nerves_hub_cli 0.9.1) lib/mix/tasks/nerves_hub.device.ex:350: Mix.Tasks.NervesHub.Device.cert_create/5
    (mix 1.10.2) lib/mix/task.ex:330: Mix.Task.run_task/3
    (mix 1.10.2) lib/mix/cli.ex:82: Mix.CLI.run_task/2

product names with spaces breaks device create command

$ mix nerves_hub.product create
NervesHub server: api.nerves-hub.org:443
NervesHub organization: konnorrigby

Creating product 'name with space'...
Local NervesHub user password: 
Product 'name with space' created.

$ mix nerves_hub.device create 
NervesHub server: api.nerves-hub.org:443
NervesHub organization: konnorrigby
Identifier (e.g., serial number): test-rpi0
Description: rpi0 test board
One or more comma-separated tags: test
Local NervesHub user password: 
Invalid product: name with space

NervesHub custom domain not working from cli

I have setup custom nerves hub instance via terraform repo. I am able to access it on my custom domain and able to perform different actions via web e.g. register, login etc.

When I try to authenticate / register via command line, I am getting this error:

NervesHub server: api.staging.customdomain.com:443
Username or email address: meraj
NervesHub password:
Authenticating...
Unhandled error: {:error, :timeout}

I am using custom instance details from environment variables. I don't know why it is not working from command line while both register / auth is working from web. Do we need to make any configuration changes for this to work?

Product name which includes space cause "Invalid Product" Error

A Product name which includes space like below is created successfully by "mix nerves_hub.product create".

def project do
  [
    app: :hello_nerves,
    name: "Hello Nerves"
    ...
  ]

But ' mix nerves_hub.product delete "Hello Nerves" ' causes "Invalid product: Hello+Nerves" Error.

I investigated this error little, then found below command finished successfully.

mix nerves_hub.product delete "Hello%20Nerves"

So this Error may be caused by url encoding of API path.

Export firmware signing keys

Add a command to export the private signing key. Currently, it's locked in a password-protected envelope which is great, but it's not usable outside of the mix tooling. Actually, if it is usable outside of mix by using some other Unix-y programs, then I think it's sufficient for my purposes to just document that.

Allow specifying org on user auth

I recently went through using mix nerves_hub.user auth successfully. But in subsequent uses of the CLI I noticed it kept defaulting my org to my username and looks like that is saved to the config by default

I think it would be nice to allow specifying the default org in the initial auth, or some easy way to change the config (which I haven't really found yet)

Validate firmware before publishing

Currently when you publish a bad firmware, it just asks for the local user cert password and then starts the upload. Then it presents the failure message after going through that whole upload process. So slow connections means it takes a long time to fail.

It would be nice if we could validate everything on the firmware locally before doing an upload.

Delete product did ok, but error

Generated klaster app
NervesHub server: manage.nervescloud.com:443
NervesHub organization: lawik
Delete product 'klaster'? [Yn] y
Unhandled error: {:ok, nil}

Add help text for "Fatal - Certificate Expired" error

The following error messages gets printed with the user cert expires:

TLS :client: In state :connection received SERVER ALERT: Fatal - Certificate Expired

The solution is to run mix nerves_hub.user auth.

It would be nice if the mix nerves_hub.* utilities would print what you're supposed to do when this happens.

mix nerves_hub.user auth failed, may be related to pbcs 0.1.3

This phenomenon may be related to pbcs 0.1.3. Because getting it back to 0.1.2 this doesn't occur.

$ asdf current 
elixir          1.11.2-otp-23   /home/pojiro/.tool-versions
erlang          23.3.4          /home/pojiro/.tool-versions

Below is the error log, nerves_hub_cli and pbcs version are printed in

$ mix nerves_hub.user auth
NervesHub server: api.nerves-hub.org:443
Username or email address: pojiro
NervesHub password: 
Authenticating...
Success

NervesHub uses client-side SSL certificates to authenticate CLI requests.

The next step will create an SSL certificate and store it in your 
'/home/pojiro/.nerves-hub' directory. A password is required to protect it. This password
does not need to be your NervesHub password. It will never be sent to NervesHub
or any other computer. If you lose it, you will need to run
'mix nerves_hub.user auth' and create a new certificate.

Please enter a local password: 
** (ArgumentError) argument error
    :erlang.iolist_to_binary({<<...>>, "-----BEGIN EC PRIVATE KEY-----\n...\n-----END EC PRIVATE KEY-----\n\n"})
    (crypto 4.9) crypto.erl:1404: :crypto.crypto_one_time/5
    (pbcs 0.1.3) lib/pbcs.ex:28: PBCS.encrypt/3
    (nerves_hub_cli 0.11.1) lib/nerves_hub_cli/user.ex:17: NervesHubCLI.User.save_certs/3
    (nerves_hub_cli 0.11.1) lib/mix/tasks/nerves_hub.user.ex:223: Mix.Tasks.NervesHub.User.generate_certificate/3
    (mix 1.11.2) lib/mix/task.ex:394: Mix.Task.run_task/3
    (mix 1.11.2) lib/mix/cli.ex:84: Mix.CLI.run_task/2

As other info, nerves_hub_cli with pbcs 0.1.2 still has a weird behavior, like below.

iex(3)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(4)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(5)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(6)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(7)> NervesHubCLI.Crypto.decrypt(encrypted_priv, password)
{:ok, "decrypted_priv"}
iex(8)> PBCS.decrypt({"", encrypted_priv}, password: password)
{:ok, "decrypted_priv"}

Once invoke from NervesHubCLI.Crypto.decrypt, PBCS.decrypt wil be ok. (I cannot understand why this happens)
see. https://github.com/nerves-hub/nerves_hub_cli/blob/main/lib/nerves_hub_cli/crypto.ex

With pbcs 0.1.3 this never return {:ok, "decrypted_priv"}, like below.

iex(3)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(4)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(5)> PBCS.decrypt({"", encrypted_priv}, password: password)
:error
iex(6)> NervesHubCLI.Crypto.decrypt(encrypted_priv, password)
{:error, "unknown"}
iex(7)> NervesHubCLI.Crypto.decrypt(encrypted_priv, password)
{:error, "unknown"}
iex(8)> NervesHubCLI.Crypto.decrypt(encrypted_priv, password)
{:error, "unknown"}

Please let me know if you need any other information. Thank you.

Manage products

The cli should let you perform the following actions on products

  • create
  • edit
  • delete

Improve text on when you need to create a device certificate

Right now when creating a device, you're prompted to create a device certificate. If you have a NervesKey on the device, you never want to do this. However, the prompt is vague on that. Also, after you've created device certs, it doesn't say what happens to them next. The docs describe that they're needed for initial provisioning, but it would be helpful to have a blurb of text here on what to do next.

Improve error message when user cert expires

Here's what happens when the user cert expires:

$ mix nerves_hub.<task that needs remote access>
Local NervesHub user password:

21:11:55.015 [info]  TLS client: In state cipher received SERVER ALERT: Fatal - Certificate Expired

Unhandled error: {:error, {:tls_alert, {:certificate_expired, 'TLS client: In state cipher received SERVER ALERT: Fatal - Certificate Expired\n'}}}

The fix is to reauthenticate:

mix nerves_hub.user auth

It would be nice to handle the error and mention the fix.

key import with an empty password doesn't work

i did a mix nerves_hub.key import keyname /path/to/key.pub /path/to/key.priv and just mashed enter until it errored out, but even tho there was an error, it actually imported the key. when i did mix nerves_hub.key delete and mashed enter it gave an error, and didn't delete it.

I'm fine with not allowing empty password, but right now it gets left in a limbo state if you try this.

Don't print out delete character for password field

This is more of a nitpick/quirky behavior. But say you're like me and always fat finger passwords then have to delete back a few characters or ctl-u the whole line. Those characters currently get printed out and create new lines for the password prompt:

jonjon@ ๐Ÿ“‚ {nerves_hub} $ mix nerves_hub.firmware list --product smartrent_hub_fw
NervesHub server: 0.0.0.0:4002
NervesHub organization: jonjon
Local NervesHub user password: ^R
Local NervesHub user password: ^R
Local NervesHub user password: ^R
Local NervesHub user password: ^U
Local NervesHub user password: 

It still works and deletes those characters. Just odd to see if all get printed out multiple times. Would be nice to have it work silently like other password prompts at the terminal

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.