Defender-autotask-client execution - command not found


:computer: Environment

  • node v14.18.1 (64-bit)
  • defender-autotask-client: 1.22.0

I am trying to update my autotask code from my local environment. However, the command is not recognized. I have used npm install defender-autotask-client.

What am I doing wrong?

:1234: Code to reproduce
defender-autotask update-code [autotask id] [folder with an index.js]

Hey @Pedro_Reyes

I just tested in local with the update-code example and looks like it's working fine. Can you share a screenshot of the command not found your' seeing? I wonder what's causing it, so taking a look at the logs and commands you executed will be great to help you further.


Hello @ernestognw ,

Thanks for the prompt reply.

This is all I get when using the command.

defender-autotask update-code *******-*******-*******-*******-******* defender/autotasks/SweepVaultFees/
bash: defender-autotask: command not found

Image as per requested:

My dependencies


Node modules with defender-autotask-client installed:

dependencies - node modules

Best regards,
Pedro Reyes

Thanks for the details @Pedro_Reyes

The package is installed in a specific directory, which means that it's not available on the global scope.
You can fix this by ether:

  1. Install the package as a global dependency (eg. npm i -g defender-autotask-client)
  2. Prefix defender-autotask ... with npx as in npx defender-autotask ... so it fetches the package before executing
  3. Or create a custom script in your package.json like in:
//  package.json
  "scripts": {
    "update-code": "defender-autotask update-code"

With number 3, you just need to run npm run update-code ... or yarn update-code ... since the package.json scripts load the locally installed dependencies.

Hope it helps!

Hello @ernestognw ,

I have installed it globally and now it detects the command. Maybe the comments in your last post will be very useful in the official documentation: As you can see, the command recommended is npm install defender-autotask-client

After doing the installatin globally I got the next error:

Error updating Autotask code: API_KEY or API_SECRET env vars are missing

I created an .env file since I had a env.json and now everything works fine.

Thanks for your help, @ernestognw .

:green_circle: Proposal
Regarding the execution of the command. It would be a nice feature when executing it that the values for API_KEY and API_SECRET can be taken directly from the Autotask secrets so there is no need for setting in the local environment these environment variables. This could be done by mapping Autotask identifiers with the Autotask secrets' private vault.

Best regards,
Pedro Reyes.

Thanks for your comments @Pedro_Reyes

I opened a PR with your notes, so thank you for raising this up.

Regarding the API keys injection, that's a great idea. I'm just curious, how would you like to consume them?

The problem I see is that the API Keys are at team level, and there could be many keys with access to manage Autotask, so I'm not sure how we would be adding keys to environment.

Also, in security terms, an Autotask could leak a secret (this is something noted on our docs), so injecting API Keys looks risky to me. What do you think?

Hello @ernestognw ,

:green_circle: Cloud key - UI proposal
What about having Cloud keys. These keys are not accessible from defender-******-client so there will be no leaked. The final user is just provided with an identifier:

The Cloud keys' identifier can be used afterwards in the Autotask to create the relationship between the Autotask and the API key and API secret that is stored in the Cloud key vault

This way everything will go through your servers. No need for the end-user to move around API keys and secrets. The identifier wouldn't even be needed, just a unique name for the Cloud key :man_shrugging:

:green_circle: Cloud key - End-user usage proposal

:point_right: Option 1

The usage could be done with a new flag in the command:

defender-autotask update-code *******-*******-*******-*******-******* defender/autotasks/SweepVaultFees/ --use-cloud-key

:point_right: Option 2

If no API key and secret is found in .env file, check if the autotask id provided in the command has any cloud key associated.

Best regards,
Pedro Reyes.

Hey @Pedro_Reyes, we really appreciate the detailed proposal and screenshots you're making and I shared it with the team for discussion, to see if we can fit it into any of our roadmap items. So take it as noted from our end.

Just to confirm, your concern is moving API Keys around, which is prone to error, right?

Although the autotask-to-cloud-key bonding proposal makes sense, I'm worried that it would make the autotaskId sensitive information and there are some users sharing that publicly on the forum for support requests, so there are still some security considerations we'd like to discuss.

If there are more details around the particular use case you have for this, we'd love to hear it som we can see if that's solved by anything in our backlog and bump its priority.

Thanks again!

Hello @ernestognw ,

You are right. However, with great power comes great responsibility :blush:

In any case, I have taken this from the wrong point of view, @ernestognw . Allow me to take a step back.

:large_blue_circle: Context
I think that when it comes to AutoTasks, the general usage will be as part of the CI/CD workflow. Here you have the example I made with GitHub Actions:

# This file was auto-generated by the Firebase CLI

name: Deploy to OpenZeppelin Defender Autotasks on merge
      - master

  # Sets environment variable
  API_KEY: ${{ secrets.DEFENDER_API_KEY }}

    runs-on: ubuntu-latest
      CI: false
      - uses: actions/checkout@v2

      # Preparing the JSON files that will be needed in the script
      - run: mkdir -p defender/autotasks/SweepVaultFees/contracts
      - run: cp -r app/src/contracts/TutorialToken.json defender/autotasks/SweepVaultFees/contracts/
      - run: cp -r app/src/contracts/NBU.json defender/autotasks/SweepVaultFees/contracts/
      - run: cp -r app/src/contracts/GNBU.json defender/autotasks/SweepVaultFees/contracts/

      # Deploying the JSON files and the script in OpenZeppelin Defender Autotask
      - run: npm ci && npm run update_defender_autotask

You can see in the next image that I have created a defender folder


In defender folder the DevOps team would update the scripts either in a separated project or as part of the current one:


The Cloud Key ID will save the fact of having two variables going around but in general terms it is a reduction that for this particular case will not be of big help. However, what it could be useful is to be able to add a single parameter when calling the command so instead of:

npm run update_defender_autotask

You could do:

npm run update_defender_autotask --cloud-key-id [cloud id]

This way you don't force the client to have an environment variable like I had to do in the earlier GitHub Actions script for using the update command.

By the way, I added the update_defender_autotask command to my package.json scripts as you suggested:

"update_defender_autotask": "npx defender-autotask update-code d225f23b-******-******-******-******688 defender/autotasks/SweepVaultFees/"

:green_circle: Proposal
If [cloud key] or [API key & secrets] are given in the command, no need for looking in the .env file. This way I can give the names I want to the cloud key (in case of being implemented) or to the API keys and secrets like for example the names I have given them in my GitHub Action secrets:

  # Sets environment variable
  API_KEY:     👉 ${{ secrets.DEFENDER_API_KEY }} 

Hope I was a bit of help :sweat_smile: Thanks for the help, @ernestognw . Wish you a good weekend :v:

Best regards,
Pedro Reyes.

1 Like

Hi again @Pedro_Reyes

We really appreciate a detailed use case and feedback for Defender. This gives us good context around the use case, and we've created an item on our roadmap to add something like this.

What we're thinking to approach this is to Inject temporary API keys into an Autotask, so you could use these so-called "Cloud keys" in your workflow. In the meantime, we'll maybe discuss the implementation details but definitely, this context helps.

We'll let you know if this is implemented.

Also wish you a good weekend, thanks again