项目作者: ojkelly

项目描述 :
Authentication and authorization tokens designed specifically for use with zero-trust microservices.
高级语言: TypeScript
项目地址: git://github.com/ojkelly/warden.git
创建时间: 2017-03-17T06:27:45Z
项目社区:https://github.com/ojkelly/warden

开源协议:Apache License 2.0

下载


Warden (Proof of Concept)

Authentication and authorization tokens designed specifically for use with zero-trust microservices.

I wrote this to explore an alternitive to JWT’s in microservices. With a bit of work this could be turned into a production level security token, however at this stage the use cases are limited. I’m leaving this here as a proof of concept.

Is it done?

Yes. But it needs a security review.

Why does this exist?

I wrote a post here

Getting Started

This package is split into 3 main classes.

The Forge manages your keys. It will generate and rotate keys for you. You implemented this as a discrete service. Ideally as it’s own container. The Forge manages two file shares, one for the Warden and one for the Guard. The keys are kept on these shares.

A Warden can create a Card, this is the bearer token you can pass around. You add this to the service that provides authentication.

A Guard can validate and extract the contents of a card. This is integrated into every service that needs to read a Card.

How to create a Card

  1. import { Warden } from 'warden';
  2. import fsp from 'fs-promise';
  3. const wardenKeySetCollection = await fsp.readJson(`${Shared Warden keys folder}/wardenKeySetCollection.json`);
  4. // Create a new warden
  5. const warden = new Warden(wardenKeySetCollection);
  6. const card = await warden.createCard({
  7. uuid: 'string',
  8. tenant: [
  9. 'string',
  10. ],
  11. roles: [
  12. 'admin',
  13. 'editor',
  14. ],
  15. hoursUntilExpiry: 1,
  16. });
  17. console.log(card);
  18. // card:
  19. // ODJmY2ZiYTIyYzJhZjlmMjc2ZWNlZjhlY2QxNjIwN2ZkOWMzNWRkODBlOWY3MGJkM2EzYWM0MzQ2MzRhNTY0NjU3YjgzYzY1NWM2MmNjNmRmNGJlOGQ5NjA0YmRmY2JiMWZkZGRmN2QwMDc1M2RiZDkwZWY5Y2IyY2MxZjQzNzBjZDI3ZDM3NDFhOGZlZjY1MGM3Yjk2ZDgyNjhhZTU3M2MzZGUzODQ2YjJmM2E1OWUwZjUwZDNjOGU4MjcxNzBlZTZmYmM1YjkwZWMwOWRhNmVhZTZjMTE3ODI4YzhlZThiMWZjYWE4OThhNTc1MmYwYjYxMzU3NmYzMjlhZThjM2E3ZmEwNDg2MTc2YTJlYmY0OTljYTY5M2Q0ZDhlYzY4ZDZkZjUxZGY2NzkzYzdhODEzOTAzMmVjYTdlMTNiNjZkZjFjNTFjMDQ4NzdkZmY4YWFlZTQ5YmNkMjllOTJhOGEyMDVkNTdkMThjMWZjYWQyMDk2ZGRjMjZlNDc5MTViMWRjNWE4YWQ4MTEyN2E5M2I4MGMyYWJjM2Y0YzIyMGFjNzc1ZTY3OGJjOGVlOWQ2Y2JjY2NkMjVlOGI1OWYzNDIzNDM2OTNhYjRmYTYyNzgwMTU1NDEwZDY2YjA3NWQwNDY3NWE3YWM1ZGU0NTllODBhNTJjZDczZGM2N2E3MGUxOGNmNWE4OGUyODFiZWVlY2U5MTg3ZmRiNzYyYjk3YjhkZmNmYzVjZDI2YTJlOTMxMDkxOWQ1NWIwZTEwNjhiNGM5MzkwNzhhNzgzMjI0NTdlNzQ3NDAzZDE4ZDgwZTFiNGY4N2I0M2M1ZWFlZjVkNmJlNGM5ZmIyNjA1MThkYTRhOWJiZTFjY2YxY2E3MTM2OGEwNzk2ZjYzNTQzZTg4YTZhMDE5OTI0NDFiMmU1NjVmMTAwM2FlZDc1ZDI0YjBhNjk3MWM0NTJhNzMzNTlkMTRhZDdmZTYyMjg0MDRkZjhkZGUzMzBkZWM5NDQzMWU0YTBlNzMzOTYxZTIzNWY0ODg4ODhjZDEwNzZmMWNjZDg4ZTY5Y2FmMGEyZGZlMmUwMWVjLjBiNTlhODcxM2JhODI5MWUwM2UzZTg5ZDhlMWJiMWM5LjdiMjVjMTMyNTk4NDZiY2YuODJmNTM5NGQ1MTFiMWQxYzQ0Y2Q5ZDBlZTU4NGEzNTIxZDViNzE3ZTFmMWJhMDlhMzY3MjNkYzhlOWFkOTJmMA==

How to use a card with a Guard

  1. import { Guard } from 'warden';
  2. import fsp from 'fs-promise';
  3. const wardenKeySetCollection = await fsp.readJson(`${Shared Guard keys folder}/guardKeySetCollection.json`);
  4. try {
  5. const checkedCard = await guard.checkCard(card);
  6. console.log(checkedCard);
  7. } catch (err) {
  8. // Card is invalid
  9. }
  10. // checkedCard:
  11. // {
  12. // uuid: '523b519b-cb8b-4fd5-8a46-ff4bab206fad',
  13. // roles: [ 'engineer', 'onCall' ],
  14. // expires: 1490232381669,
  15. // tenant: [ '48d2d67d-2452-4828-8ad4-cda87679fc91' ]
  16. // }

The key sets are managed by the Forge class. This class looks after key rotate and the initial generation.
You should implement this as a completely seperate container, either running with an internal cronjob, or
set to spin up every hour.

Inside the container you need to have two file mounts, one for the Wardens keys and one the Guards. Pass the
location of these to the Forge constructor. The Forge will load up the files, check if any keys have expired,
and rotate the collection if they have.

How to check and rotate the keys with Forge

  1. import { Forge } from 'warden';
  2. const forge = new Forge({
  3. // The path to the directory where the Warden keys are stored.
  4. // This should be a mount shared with the Wardens.
  5. // Forge needs read-write access, Wardens must have read-only
  6. wardenKeySetDirectory: '/srv/wardenKeys',
  7. // The path to the directory where the Guards keys are stored.
  8. // This should be a mount shared with the Guards.
  9. // Forge needs read-write access, Guards must have read-only
  10. guardKeySetDirectory: '/srv/guardKeys',
  11. // Optionally you can set the maximum number of key sets to
  12. // keep on rotation. When a keyset expires it is replace with
  13. // a new one.
  14. maxKeySetsValid: 3,
  15. // Optionally you can set the maximum number of days a keyset
  16. // is valid for.
  17. // This must be greater or equal to the maximum time a Card
  18. // is valid for, becuase once the key a Card was created with
  19. // is rotated, that Card becomes invalid.
  20. maxKeySetValidDays: 5,
  21. })
  22. // This will check to see if any keys exist
  23. // Then it will either create new ones, or cycle through
  24. // and replace exipered ones.
  25. try {
  26. await forge.rotateKeys();
  27. } catch(err){
  28. console.warn(err);
  29. // If this fails you should crash the process and try again
  30. process.exit(1);
  31. }

Configuration

This module is an answer to the state of JWT. In learning from the mistakes there, and apply that to
the specific problem of authentication and authorization in a zero-trust microservices system, you have
almost no configuration options.

There is no capability to change the cryptography used, or how it’s used. These options are baked into
the library itself. Any change to the cryptography used, is considred a breaking change and will
be identified with a major version bump.

You do however have control over the expiry length of Cards.


Owen Kelly