;;; -*- Lisp -*- ;;; $Id$ ;;; Copyright (C) 2007--2008 American Registry for Internet Numbers ("ARIN") ;;; ;;; Permission to use, copy, modify, and distribute this software for any ;;; purpose with or without fee is hereby granted, provided that the above ;;; copyright notice and this permission notice appear in all copies. ;;; ;;; THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH ;;; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ;;; AND FITNESS. IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, ;;; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ;;; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE ;;; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ;;; PERFORMANCE OF THIS SOFTWARE. ;;; Scratch pad for working out API design for RPKI engine. ;;; ;;; This file is pseudocode, I just wanted to take advantage of ;;; emacs's built-in support for languages with reasonable syntax. ;;; ;;; Terminology: ;;; ;;; - IRBE: Internet Registry Back End ;;; ;;; - RE: RPKI Engine ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Protocol operations between IRBE and RE. ;;; ;;; This is really two separate protocols over channels that might or ;;; not be the same. Both are client/server protocols, but for some ;;; the RE is the client and for others the IRBE is the client. ;;; ;;; This set of operations are initiated by the IRBE. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; This part of the protcol uses a kind of message-passing. Each ;;; object that the RE knows about takes five messages: :create, :set, ;;; :get, :list, and :destroy. Actions which are not just data ;;; operations on objects are handled via an SNMP-like mechanism, as ;;; if they were fields to be set. For example, to generate a keypair ;;; one "sets" the :generate-keypair field of a biz-signing-context ;;; object, even though there is no such field in the object itself. ;;; This is a bit of a kludge, but the reason for doing it as if these ;;; were variables being set is to allow composite operations such as ;;; creating a biz-signing-context, populating all of its data fields, ;;; and generating a keypair, all as a single operation. With this ;;; model, that's trivial, otherwise it's at least two round trips. ;;; ;;; Fields can be set in either :create or :set operations, the ;;; difference just being whether the object already exists. A :get ;;; operation returns all visible fields of the object. A :list ;;; operation returns a list containing what :get would have returned ;;; on each of those objects. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; "Self" ID context -- one RE instance. In degenerate case there ;; will be only one, but in hosting environments there might be many. ;; ;; We haven't yet defined any standard preferences, so none are shown. ;; ;; Extensions might also show up as preferences, using the ;; extension-preference syntax. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (self :action :create (:extension-preference "name" "Launcelot") (:extension-preference "quest" "Holy Grail")) => (self :self-id 42) (self :action :set :self-id 42 (:extension-preference "color" "Blue") ;; ;; objects have a lot of actions: ;; (:rekey) ; Change all RPKI keys in this context now (:reissue) ; Reissue any cert with changed keys (:revoke) ; Revoke any old keys (:run-now) ; Run this self context now (:publish-world-now)) ; Publish everything in this context now => (self :self-id 42) (self :action :get :self-id 42) => (self :self-id 42 (:extension-preference "name" "Launcelot") (:extension-preference "quest" "Holy Grail") (:extension-preference "color" "Blue")) (self :action :list) => ((self :self-id 42 (:extension-preference "name" "Launcelot") (:extension-preference "quest" "Holy Grail") (:extension-preference "color" "Blue")) (self :self-id 99 (:extension-preference "name" "Arthur, King of the Britons") (:extension-preference "quest" "Holy Grail") (:extension-preference "airspeed-velocity-of-an-unladen-swallow" "African or European swallow?"))) (self :action :destroy :self-id 42) => (self :self-id 42) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Business signing key context -- bundles all the stuff we need to ;; sign outgoing CMS messages with a business key. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (biz-signing-context :action :create :self-id 42 (:signing-cert cert1) ;; ;; Actions: ;; (:generate-keypair :key-type :rsa :hash-alg :sha1 :key-length 2048)) => (biz-signing-context :biz-signing-context-id 17 (:pkcs10-cert-request req)) (biz-signing-context :action :set :self-id 42 :biz-signing-context-id 17 (:signing-cert cert2)) => (biz-signing-context :biz-signing-context-id 17) (biz-signing-context :action :get :self-id 42 :biz-signing-context-id 17) => (biz-signing-context :biz-signing-context-id 17 (:signing-cert cert1) (:signing-cert cert2) (:public-key key)) (biz-signing-context :action :list :self-id 42) => ((biz-signing-context :biz-signing-context-id 17 (:signing-cert cert1) (:signing-cert cert2) (:public-key key))) (biz-signing-context :action :destroy :self-id 42 :biz-signing-context-id 17) => (biz-signing-context :biz-signing-context-id 17) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Parent context -- represents one parent of this RE ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (parent :action :create :self-id 42 (:ta ta) (:uri uri) (:sia-base sia-base) (:biz-signing-context biz-signing-context) (:repository repository)) => (parent :parent-id 666) (parent :action :set :self-id 42 :parent-id 666 (:ta ta) (:uri uri) (:sia-base sia-base) (:biz-signing-context biz-signing-context) (:repository repository) ;; ;; Actions: ;; (:rekey) ; Change all keys now (:reissue) ; Reissue all certs with changed keys now (:revoke)) ; Revoke any old keys now => (parent :parent-id 666) (parent :action :get :self-id 42 :parent-id 666) => (parent :parent-id 666 (:ta ta) (:uri uri) (:sia-base sia-base) (:biz-signing-context biz-signing-context) (:repository repository)) (parent :action :list :self-id 42 :parent-id 666) => ((parent :parent-id 666 (:ta ta) (:uri uri) (:sia-base sia-base) (:biz-signing-context biz-signing-context) (:repository repository))) (parent :action :destroy :self-id 42 :parent-id 666) => (parent :parent-id 666) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Child context -- represents one child of this RE ;; ;; "child-db-id" may be unnecessary -- old API had both "child" and ;; "child-id", the second of which was a settable attribute of child, ;; I'm not quite sure what it was, so here I'm calling it child-db-id ;; in case we need it for something. Perhaps this corresponds to the ;; optional child ID in the list-resources callback to the IRBE? ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (child :action :create :self-id 42 (:ta ta) (:biz-signing-context biz-signing-context) (:child-db-id child-db-id)) => (child :child-id 3) (child :action :set :self-id 42 :child-id 3 (:ta ta) (:biz-signing-context biz-signing-context) (:child-db-id child-db-id) (:reissue)) ; Reissue any certs to this child now => (child :child-id 3) (child :action :get :self-id 42 :child-id 3) => (child :child-id 3 (:ta ta) (:biz-signing-context biz-signing-context) (:child-db-id child-db-id)) (child :action :list :self-id 42 :child-id 3) => ((child :child-id 3 (:ta ta) (:biz-signing-context biz-signing-context) (:child-db-id child-db-id))) (child :action :destroy :self-id 42 :child-id 3) => (child :child-id 3) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Repository context -- represents one repository in which this RE ;; publishes objects it signs. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (repository :action :create :self-id 42 (:uri uri) (:ta ta) (:biz-signing-context biz-signing-context)) => (repository :repository-id 120) (repository :action :set :self-id 42 :repository-id 120 (:uri uri) (:ta ta) (:biz-signing-context biz-signing-context)) => (repository :repository-id 120) (repository :action :get :self-id 42 :repository-id 120) => (repository :repository-id 120 (:uri uri) (:ta ta) (:biz-signing-context biz-signing-context)) (repository :action :list :self-id 42 :repository-id 120) => ((repository :repository-id 120 (:uri uri) (:ta ta) (:biz-signing-context biz-signing-context))) (repository :action :destroy :self-id 42 :repository-id 120) => (repository :repository-id 120) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Route Origin objects (prototype and control for ROAs) ;; ;; Previous versions of this protocol handled this via queries from ;; the RE back into the IRBE, but the design group now believes that ;; an imperative interface makes more sense. We stick to the same ;; general object model used above because ROAs are published objects, ;; thus the IRBE presumably wants some kind of handle on the ROA. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (route-origin :action :create :self-id 42) => (route-origin :route-origin-id 88) (route-origin :action :set :self-id 42 :route-origin-id 88 :as-number 12345 :publish :yes (:ipv4-prefix 10.0.0.44 32) (:ipv4-range 10.2.0.6 10.2.0.77) (:ipv6-prefix 2002:a00:: 48) (:ipv6-range 2002:a02:6:: 2002:a02:4d::)) => (route-origin :route-origin-id 88) (route-origin :action :get :self-id 42 :route-origin-id 88) => (route-origin :route-origin-id 88 (:as-number 12345) (:ipv4-prefix 10.0.0.44 32) (:ipv4-range 10.2.0.6 10.2.0.77) (:ipv6-prefix 2002:a00:: 48) (:ipv6-range 2002:a02:6:: 2002:a02:4d::)) (route-origin :action :list :self-id 42) => ((route-origin :route-origin-id 88 (:as-number 12345) (:ipv4-prefix 10.0.0.44 32) (:ipv4-range 10.2.0.6 10.2.0.77) (:ipv6-prefix 2002:a00:: 48) (:ipv6-range 2002:a02:6:: 2002:a02:4d::))) (route-origin :action :destroy :self-id 42 :route-origin-id 88) => (route-origin :route-origin-id 88) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; "Blind object signing" would probably be another imperative message ;; to be added above, similar to (route-origin). ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Protocol operations between IRBE and RE. ;;; ;;; This is really two separate protocols over channels that might or ;;; not be the same. Both are client/server protocols, but for some ;;; the rpki engine and for others the irbe is the client. ;;; ;;; This set of operations are initiated by the RE. ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (list-resources :self-id 42 ; issuer id :child id) ; subject id => (resources :valid-until 2008-04-01T00:00:00Z ((:ipv4-prefix 10.0.0.44 32) (:ipv4-prefix 10.3.0.44 32) (:ipv6-prefix fe80:dead:beef:: 48) (:as-number 666)) ((:subject-name "wombats are us") ; Allowed in protocol, but RE may reject with error (:ipv4-prefix 10.2..0.6 32) (:ipv6-prefix fe80:dead:beef:: 48) (:ipv6-range fe80:dead:beef:: fe80:dead:beef::49) (:as-number 666)) ...) (report-error :self-id 42 :error-token :your-hair-is-on-fire :bag-of-data whatever) => ()