The way most software systems are secured today is fundamentally flawed. They rely on “perimeter” security: a firewall guarding access to a protected network. Inside the perimeter traffic is mostly trusted. This paradigm relies on assumptions that nobody actually believes are true: that people are never careless or dishonest and never make mistakes. One slip up that allows an attacker inside the perimeter and it’s game over.
Security considerations aside, perimeter security is expensive and annoying. Maintaining a perimeter is an operational burden. VPNs are notoriously frustrating for users. Access requests that would help someone do their job faster are frequently denied because the perimeter is all-or-nothing and fine-grained access cannot be granted.
A better security model exists. Instead of relying on IP and MAC addresses to determine access we can cryptographically authenticate the identity of people and software making requests. It’s a simple concept, really: what matters is who or what is making a request, not where a request comes from. In short, access should be based on identity.
This general approach to security was branded “zero trust” by Forrester in 2010. Google has called the idea “BeyondCorp” in the context of corporate IT (they moved to this model to improve their own security after Operation Aurora). Names aside, the idea is obviously good. Zero trust concepts improve security and reduce security overhead.
Zero trust is an idea, not a technology. But there are a number of technologies that are relevant to zero trust architectures: authenticated encryption (X.509, TLS), single sign-on (OAuth OIDC, SAML), multi-factor authentication (OATH OTP, FIDO U2F), encryption mechanisms (JWE, NaCl), and verifiable claims (JWT, SAML assertions), to name a few.
Unfortunately these technologies are complex. They’re hard to work with, hard to debug, and hard to string together to build and operate a complete system. This is largely a tooling problem. No good tools exist for working with zero trust primitives. Today we’re announcing the open source release of the
stepcommand line utility to help fill that gap.
step is a zero trust swiss army knife. It is an easy-to-use and hard-to-misuse utility that implements a broad set of useful zero trust primitives. The goal is to make it easier for developers, operators, and security professionals to experiment with, debug, and automate zero trust systems. Over time we plan to add infrastructure components and user-facing functionality that make building and using zero trust systems even easier.
What we’re releasing today is just the beginning. It's an early release, and none of the APIs are stable yet. It’s incomplete, and a bit rough around the edges, but it’s already full of useful functionality. Here’s some stuff you can do with
- Generate X.509 root certificates, intermediate certificates, and leaf certificates for use with TLS
- Use single sign-on to make authenticated requests using OAuth and OIDC
- Automate multi-factor authentication enrollment by generating OATH TOTP keys and validating TOTP passcodes
- Encrypt and decrypt data using JSON Web Encryption (JWE) and NaCl
- Sign and verify data using JSON Web Tokens (JWT), JSON Web Signatures (JWS), and NaCl
- Inspect and lint X.509 certificates and JSON Web Tokens (JWTs)
Our goal is to build a forgiving tool with safe and sane defaults that makes all of this as easy as possible.
Some examples of
step in action
Note that this is an alpha release of
step. None of these APIs are stable yet.
On macOS using brew:
$ brew install step
On Linux using deb:
$ wget https://github.com/smallstep/cli/releases/download/v0.8.5/step_0.8.5_amd64.deb $ sudo dpkg -i step_0.0.1_amd64.deb
Create a root CA, an intermediate, and a leaf X.509 certificate. Bundle the leaf with the intermediate for use with TLS:
$ step certificate create --profile root-ca \ "Example Root CA" root-ca.crt root-ca.key $ step certificate create \ "Example Intermediate CA 1" intermediate-ca.crt intermediate-ca.key \ --profile intermediate-ca --ca ./root-ca.crt --ca-key ./root-ca.key $ step certificate create \ example.com example.com.crt example.com.key \ --profile leaf --ca ./intermediate-ca.crt --ca-key ./intermediate-ca.key $ step certificate bundle \ example.com.crt intermediate-ca.crt example.com-bundle.crt
Extract the expiration date from a certificate (requires
$ step certificate inspect example.com.crt --format json | jq -r .validity.end $ step certificate inspect https://smallstep.com --format json | jq -r .validity.end
JSON Object Signing & Encryption (JOSE)
$ step crypto jwk create pub.json key.json $ cat pub.json | step crypto jwk keyset add keys.json $ JWT=$(step crypto jwt sign \ --key key.json \ --iss "firstname.lastname@example.org" \ --aud "email@example.com" \ --sub "firstname.lastname@example.org" \ --exp $(date -v+15M +"%s"))
Verify your JWT and return the payload:
$ echo $JWT | step crypto jwt verify \ --jwks keys.json --iss "email@example.com" --aud "firstname.lastname@example.org"
Login with Google, get an access token, and use it to make a request to Google's APIs:
curl -H"$(step oauth --header)" https://www.googleapis.com/oauth2/v3/userinfo
Login with Google and obtain an OAuth OIDC identity token for single sign-on:
$ step oauth \ --provider https://accounts.google.com \ --client-id 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com \ --client-secret udTrOT3gzrO7W9fDPgZQLfYJ \ --bare --oidc
Obtain and verify a Google-issued OAuth OIDC identity token:
$ step oauth \ --provider https://accounts.google.com \ --client-id 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com \ --client-secret udTrOT3gzrO7W9fDPgZQLfYJ \ --bare --oidc \ | step crypto jwt verify \ --jwks https://www.googleapis.com/oauth2/v3/certs \ --iss https://accounts.google.com \ --aud 1087160488420-8qt7bavg3qesdhs6it824mhnfgcfe8il.apps.googleusercontent.com
Generate a TOTP token and a QR code:
$ step crypto otp generate \ --issuer smallstep.com --account email@example.com \ --qr smallstep.png > smallstep.totp
Scan the QR Code using Google Authenticator, Authy or similar software and use it to verify the TOTP token:
$ step crypto otp verify --secret smallstep.totp
What’s smallstep and why are we releasing this tool?
Smallstep makes software that helps teams build and operate distributed systems. We’re venture-backed by Accel, Upside Partnership, Boldstart, and a whole bunch of other awesome investors. We make money by licensing on-prem software that makes building and operating robust large scale systems easier. Our interest in zero trust security is motivated by this broader mission.
We put together the
step command line utility to debug, operate, and automate the distributed systems infrastructure we provide to our customers. The tool leverages open source and open standards extensively. It's written in Go and uses golang's excellent crypto, x/crypto and x509 libraries. It also uses Square's go-jose library, additional x509 utilities from the ZMap team, and numerous other libraries and contributions. This wasn't a solo effort. So open sourcing seemed like the right thing to do. Selfishly, we also want you to know who we are and want to build a community around our technologies. We believe that open source is a great way to build a grassroots following.
On that note, a quick and shameless plug — our complete stack includes everything you need to fully realize zero trust. We have an online certificate authority for TLS and SSH, an OAuth identity provider, a policy language and policy engine, an identity-aware and policy-enforcing proxy. Some of these components will eventually make their way into the open source
step offering. Some enterprise features will be held back and monetized. If you’re interested in this sort of stuff please contact us.
What we’re releasing today is just the beginning. There’s a lot that still needs to be cleaned up. Our highest priority is documentation, which is incomplete and isn’t as pretty as we’d like it to be. Many commands are missing fairly obvious options which we'll be adding over the coming weeks. Please open an issue if there's anything you'd like to see.
We also have a long roadmap of features to add. We want to support the ACME, FIDO U2F, and SAML protocols. We want to integrate with HSMs, TPMs, and operating system facilities for managing private keys and passwords. We'd like to add support for working with OCSP, CRL, and certificate transparency lists. We want to make it easier to automate zero trust in cloud environments by working with instance identity claims as well as cryptographic key management and encryption services from popular vendors.
More conceptually, we’d like to raise the level of abstraction for security. What we’re releasing today is still pretty in-the-weeds for day-to-day use. There are a small number of operations that most users need regularly and that we’d like to provide abstractly as top-level commands in the
- Login and logout
- Make an authenticated request
- Encrypt data for a recipient / decrypt data from a sender
- Sign data / verify a signature
- Enroll a device, a hardware factor, or a new public key
- Request access to some data or service
You can already do most of these things with
step today. In fact, there are a lot of ways to implement each of these operations, which is precisely the problem. Most users and software developers should be shielded from these details both for their own benefit and for the benefit of implementors. By exposing functionality through abstract interfaces the implementation is easier to change. Your security story can be incrementally improved. You can easily switch from AES-GCM to ChaCha20-Poly1305, or from OAuth tokens to client certificates. All without code changes and without impacting anyone’s workflow.
Here's a taste of what requesting access might look like, for example:
There’s a lot that needs to happen to realize this vision. We'd love your help and support to get there. Star us (or fork us) on GitHub. Follow us on twitter. If you’re interested in our other products please contact us. And if you like working on these sorts of things drop us a line, we're always hiring.
We're very excited to finally be sharing more publicly. We want your feedback, so please tell us what you think and how we can make
step better. We look forward to sharing more in the future.