Some API security hygiene tips.
We're all API people here, right?
I have some tips to share.
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!
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).
Treat Basic Authorization headers the same as passwords, because any observer can easily extract your password from that.
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!
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:
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.
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.
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!
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:
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 700
modes.
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!
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.
YES, you're right, of course Marsh. The -u is not evil, in itself. It's just the displaying of passwords...
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
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.
yes, thank you!
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 -
@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