Do you use curl? Stop using -u. Please use curl -n and .netrc

Some API security hygiene tips.

We're all API people here, right?

I have some tips to share.

  1. Don't ever put passwords in a community post. Also: avoid displaying passwords or Basic Auth headers in a terminal session, even for a moment.

    Several times I have seen posts here on the Apigee community, showing that a curl command like this:

     curl -X POST -v -u 'my_username:my_password' . https://foobar/slksls
    	

    This probably goes without saying for most of us here, but let's just say it ... it's a really really bad idea to include your credentials in a public post.

    I often suggest to people here to provide as much detail as possible, when asking questions. This helps readers (like me) understand clearly what the person is asking about. And the curl command might be exactly the command the person has run in their own terminal session, and it's helpful for people here on community to know the exact command. But not credentials!

  2. Don't put user credentials in email. Even email to Apigee support, or individual Apigeeks. Email is not a secure communications channel.

    When you send an email to Apigee support, that email gets stored automatically into a database, and your password or credential will be there forever, and be viewable by a variety of people. Avoid!

    Avoid writing down your password in any communication that you send anywhere, even to people you trust (like Apigee support).

  3. Treat Basic Authorization headers the same as passwords, because any observer can easily extract your password from that.

  4. Don't show passwords or user credentials on screen-shares!

    Sometimes people get on web meetings (hangouts) with Apigeeks and show commands they're running. Don't do this if your credentials are visible!

  5. Be aware that if you use curl -v, your terminal session will show headers including the authorization header, which means your credentials. Be careful showing any output of curl -v in email or community posts or screenshares!

ok, that's what not to do. What *should* you do?

Here's what I suggest:

  1. Option 1: use curl -n

    If you have OSX or Linux, create a ~/.netrc file and insert your creds there, and use curl -n. [ Instructions]

    chmod the file to 400. curl knows how to extract your creds from the file silently. You never have to type creds on the command line again.

    If you run Windows, and use curl, you must name the file _netrc . As on *nix, the file should be in your home directory, and should have appropriate permissions.

    For Administrative APIs for Apigee Edge, my .netrc file looks like this:

    machine api.enterprise.apigee.com 
      login dchiesa@google.com
      password NotTelling-notever-no-way
    	

    You can include multiple stanzas like that, one for each API endpoint. When you pass the -n option to curl, instead of -u USER:PASS, it tells curl, "if you ever connect with api.enterprise.apigee.com, then use THESE creds" . This also works with OPDK, or any HTTP endpoint curl can address. I have creds for Jira, various devportals, heroku, and other things all in my .netrc.

    Using .netrc to store creds lets you use curl in terminal sessions, without ever revealing your password. This means you can invite anyone to view your screen, with no risk. You can screenshot, no problem. Screen share, no problem. Copy/paste, no problem!

    Also, it's way more convenient than keying in your creds each time!

    Remember: don't use curl -v, because that will show the basic auth header. You probably want curl -i anyway, which is less verbose and more useful than -v in most cases.

  2. Option 2: use curl -u, and environment variables

    Insert your credentials into an environment variable, and do something like this:

    curl -u ${BASIC_AUTH_HEADER} https://foo.bar
    

    This works to obscure your password/credential in a terminal session that someone else might see directly or via screen share. There are some caveats, though. Again, watch out for -v. And you will need a different environment variable for each API endpoint.

  3. Option 3: don't use curl

    Use some other tool that hides the credentials completely. Like PAW or Wiztools rest client.

    I think Postman doesn't quite hide the creds completely. So be careful!

AND, if you are focused on Apigee Edge Admin APIs, there's a new option for using OAuth tokens. This is something relatively new with Apigee Edge. It allows you to send a time-limited OAuth token in the Authorization header of requests, which means the window of vulnerability is lower.

Encourage others (colleagues, partners) to follow good behavior too.

I'm interested to hear feedback on these suggestions!

Comments
Not applicable

Thanks @Dino. Useful tip. I agree, there are many risks of showing your credentials and leave trace in your bash history.

IMO - A reasonable solution between .netrc and leaving your creds unprotected is to use environment variables. The reason I like it is because of this:

  • It's portable. I can perfectly share my command with anyone without disclosing my credentials.
curl https://api.enterprise.apigee.com/v1/organizations/testmyapi/apis/weatherapi -X DELETE -u $ae_username:$ae_password

With this approach my bash history won't show any trace of my credentials. I'll see exactly the command I ran.

4550  curl https://api.enterprise.apigee.com/v1/organizations/testmyapi/apis/weatherapi -X DELETE -u $ae_username:$ae_password<br>

If you do this, follow guidelines for protecting those .profile files that set those environment variables with 750 or 700modes.

Also, if you feel it's too verbose or tiring to type everytime -u $ae_username:$ae_password, I use OhMyZSH http://ohmyz.sh/ for autocomplete. It's great tooling for command line junkies like me 😉

Like it, hate it. Let us know!

Marsh
Staff

My only objection is the tarring-and-feathering of -u… by itself it isn't bad, it's only when you shim a `:password` into it that you run into trouble.

If you just pass -u with a username, you'll be prompted to enter a host password (with masked chars). This is great because it 1) keeps you from leaking your password when screen sharing and 2) keeps secrets out of your shell history.

But if you get sick of typing you password all the time, use -n and let .netrc make that easy for you.

DChiesa
Staff

YES, you're right, of course Marsh. The -u is not evil, in itself. It's just the displaying of passwords...

season88481
New Member

In the first line of the sample netrc file, I found using http://api.enterprise.apigee.com is not correct.

Removing the http:// schema might help.

machine api.enterprise.apigee.com 
login dchiesa@google.com
password NotTelling-notever-no-way
itravindrasingh
New Member

Thank you Dino for sharing this great article. this is very important when we work on client project and shares the screenshots or error details in the public channel. This should be a checklist of every API developer.

dchiesa1
Staff

yes, thank you!

DEye
Bronze 1
Bronze 1

Hello,
A somewhat  better solution than -u is - H with an encrypted credentials "hash"

url -s -k -H 'Authorization: Basic Y2FhZG1pbjpzcGVjdHJ1bQo=' 'http://10.11.11.1:8080/yourtool/restful/0x1004e37?attr=0x19bffb'

The Link above on using -n is broken -

ZoneAlpha1
Bronze 1
Bronze 1

@DEye  Just wanted to check your solution.  You say use the -H option to add a new header with an encrypted hash.  In your example you are just adding a header with a base64 encoded string which isn't a hash, so it's entirely unencrypted. By reversing the base64 encoding in your example I can get the username and password: caadmin:spectruB

Version history
Last update:
‎04-07-2017 11:18 AM
Updated by: