Sophie

Sophie

distrib > Fedora > 16 > i386 > by-pkgid > 2f06e4e3916ddccb4be0182b4ece60c6 > files > 23

certmonger-0.59-1.fc16.i686.rpm

The life cycle of a certificate:
	* Generating a key pair.
	* Generating a CSR containing public key.
	* Submitting CSR to a CA.
	* Checking for response from CA.
	* Waiting for certificate to near expiration.
Administrative action can also add these states:
	* On hold
	* Revoked

We model that life cycle as a state machine.

Now with some arbitrarily-named states for our per-certificate state machine:
	* Generating a key pair.
	  States: NEED_KEY_PAIR, GENERATING_KEY_PAIR [*],
		  NEED_KEY_GEN_TOKEN, NEED_KEY_GEN_PIN, HAVE_KEY_PAIR
	* Reading info about key pair.
		  NEED_KEYINFO, READING_KEYINFO [*],
		  NEED_KEYINFO_READ_TOKEN, NEED_KEYINFO_READ_PIN, HAVE_KEYINFO
	* Generating a CSR containing public key.
	  States: NEED_CSR, GENERATING_CSR [*],
		  NEED_CSR_GEN_TOKEN, NEED_CSR_GEN_PIN, HAVE_CSR
	* Submitting CSR to a CA.
	  States: NEED_TO_SUBMIT, SUBMITTING [*]
	* Don't know which CA to submit to.
	  States: NEED_CA [*]
	* Don't have complete information about CA.
	  States: CA_UNCONFIGURED [*]
	* Can't contact CA.
	  States: CA_UNREACHABLE [*]
	* Rejected, very sad.
	  States: CA_REJECTED [*]
	* CA is thinking.
	  States: CA_WORKING [*]
	* Saving certificate to the desired location and parsing it for the
	  information we think is interesting.
	  States: NEED_TO_SAVE_CERT, PRE_SAVE_CERT[*],
		  START_SAVING_CERT, SAVING_CERT [*],
		  NEED_TO_READ_CERT, READING_CERT [*],
		  SAVED_CERT, POST_SAVED_CERT[*]
	* Waiting for certificate to near expiration.
	  States: MONITORING
	* Notifying the admin of impending/passed expiration.
	  States: NEED_TO_NOTIFY, NOTIFYING [*]
	* Waiting for user input
	  States: NEED_GUIDANCE [*]
	* Getting our bearings
	  States: NEWLY_ADDED,
		  NEWLY_ADDED_READING_KEYINFO [*],
		  NEWLY_ADDED_NEED_KEYINFO_READ_TOKEN,
		  NEWLY_ADDED_NEED_KEYINFO_READ_PIN,
		  NEWLY_ADDED_START_READING_CERT,
		  NEWLY_ADDED_READING_CERT [*],
		  NEWLY_ADDED_DECIDING [*]
[*] Denotes states in which we have to wait for instructions from the user
    or completion of interaction with external systems.

State logic:
	NEED_KEY_PAIR:
		start-key-generation
		state_next = GENERATING_KEY_PAIR
		state_transition = now
		break

	GENERATING_KEY_PAIR:
		if starting-up
			state_next = NEED_KEY_PAIR
			state_transition = now
		else
			if keygen-finished
				if key-was-stored-successfully
					state_next = HAVE_KEY_PAIR
					state_transition = now
				elseif key-store-needs-token
					state_next = NEED_KEY_GEN_TOKEN
					state_transition = now
				elseif key-store-needs-pin
					state_next = NEED_KEY_GEN_PIN
					state_transition = now
				else
					state_next = NEED_KEY_PAIR
					state_transition = now
			else
				state_next = GENERATING_KEY_PAIR
				state_transition = when-notified
		break

	NEED_KEY_GEN_TOKEN:
		if starting-up
			state_next = NEED_KEY_PAIR
			state_transition = soon
		break

	NEED_KEY_GEN_PIN:
		if starting-up
			state_next = NEED_KEY_PAIR
			state_transition = now
		break

	HAVE_KEY_PAIR:
		state_next = NEED_KEYINFO
		state_transition = now
		break

	NEED_KEYINFO:
		start-reading-key-information
		state_next = READING_KEYINFO
		state_transition = now
		break

	READING_KEYINFO:
		if starting-up
			state_next = NEED_KEYINFO
			state_transition = now
		else
			if finished-reading-key-information
				state_next = HAVE_KEYINFO
				state_transition = now
			elseif key-store-needs-token
				state_next = NEED_KEYINFO_READ_TOKEN
				state_transition = now
			elseif key-store-needs-pin
				state_next = NEED_KEYINFO_READ_PIN
				state_transition = now
			else
				state_next = NEED_KEY_PAIR
				state_transition = now
		break

	NEED_KEYINFO_READ_TOKEN:
		if starting-up
			state_next = NEED_KEYINFO
			state_transition = soon
		break

	NEED_KEYINFO_READ_PIN:
		if starting-up
			state_next = NEED_KEYINFO
			state_transition = soon
		break

	HAVE_KEYINFO:
		state_next = NEED_CSR
		state_transition = now
		break

	NEED_CSR:
		if starting-up
			state_next = HAVE_KEYINFO
			state_transition = now
		else
			if don't-have-a-full-template
				fill-in-template-values-based-on-defaults
			start-csr-generation-using-template-values
			state_next = GENERATING_CSR
			state_transition = now
		break

	GENERATING_CSR:
		if starting-up
			state_next = HAVE_KEYINFO
			state_transition = now
		else
			if csrgen-finished
				if csr-was-stored
					state_next = HAVE_CSR
					state_transition = now
				elseif key-store-needs-token
					state_next = NEED_CSR_GEN_TOKEN
					state_transition = now
				elseif key-store-needs-pin
					state_next = NEED_CSR_GEN_PIN
					state_transition = now
				else
					state_next = NEED_CSR
					state_transition = now
			else
				state_next = GENERATING_CSR
				state_transition = when-notified
		break

	NEED_CSR_GEN_TOKEN:
		if starting-up
			state_next = HAVE_KEYINFO
			state_transition = soon
		break

	NEED_CSR_GEN_PIN:
		if starting-up
			state_next = HAVE_KEYINFO
			state_transition = now
		break

	HAVE_CSR:
		state_next = NEED_TO_SUBMIT
		state_transition = now
		break

	NEED_TO_SUBMIT:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		else
			start-csr-submission
			if csr-submission-started
				state_next = SUBMITTING
				state_transition = now
			else
				if don't-know-a-ca
					state_next = NEED_CA
					state_transition = now
		break

	SUBMITTING:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		else
			if csr-submission-attempt-completed
				if ca-issued-cert
					state_next = NEED_TO_SAVE_CERT
					state_transition = now
				elseif ca-rejected-us
					if already-had-a-cert
						state_next = MONITORING
						state_transition = now
					else
						state_next = CA_REJECTED
						state_transition = later
				elseif ca-is-unreachable
					store-ca-cookie
					state_next = CA_UNREACHABLE
					state_transition = later
				elseif ca-is-thinking-about-it-and-have-cookie
					store-ca-cookie
					state_next = CA_WORKING
					state_transition = soon
				elseif ca-is-underconfigured
					if already-had-a-cert
						state_next = MONITORING
						state_transition = now
					else
						store-ca-cookie
						state_next = CA_UNCONFIGURED
						state_transition = later
				else
					state_next = NEED_GUIDANCE
					state_transition = now
			else
				state_next = SUBMITTING
				state_transition = when-notified
		break

	NEED_TO_SAVE_CERT:
		if pre-save-command-configured
			start-configured-pre-save-command
			state_next = PRE_SAVE_CERT
			state_transition = now
		else
			state_next = START_SAVING_CERT
			state_transition = now
		break

	PRE_SAVE_CERT:
		if starting-up
			state_next = NEED_TO_SAVE_CERT
			state_transition = now
		else
			if pre-save-completed
				state_next = START_SAVING_CERT
				state_transition = now
		break

	START_SAVING_CERT:
		start-saving-cert
		state_next = SAVING_CERT
		state_transition = now
		break

	SAVING_CERT:
		if starting-up
			state_next = NEED_TO_SAVE_CERT
			state_transition = now
		else
			if cert-save-completed
				state_next = NEED_TO_READ_CERT
				state_transition = now
		break

	NEED_TO_READ_CERT:
		start-reading-cert
		state_next = READING_CERT
		state_transition = now
		break

	READING_CERT:
		if starting-up
			state_next = NEED_TO_READ_CERT
			state_transition = now
		else
			if cert-read-completed
				state_next = SAVED_CERT
				state_transition = now
		break

	SAVED_CERT:
		if post-save-command-configured
			start-configured-post-save-command
			state_next = POST_SAVED_CERT
			state_transition = now
		else
			state_next = MONITORING
			state_transition = now
		break

	POST_SAVED_CERT:
		if starting-up
			state_next = SAVED_CERT
			state_transition = now
		else
			if post-save-completed
				state_next = MONITORING
				state_transition = now

	CA_REJECTED:
		state_transition = soon
		break

	CA_WORKING:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		else
			state_next = NEED_TO_SUBMIT
			state_transition = soon
		break

	CA_UNREACHABLE:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		else
			state_next = NEED_TO_SUBMIT
			state_transition = soon
		break

	CA_UNCONFIGURED:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		break

	NEED_CA:
		if starting-up
			state_next = HAVE_CSR
			state_transition = now
		break

	NEED_GUIDANCE:
		if have-guidance
			state_next = as-guided
			state_waitfor = now
		else
			state_next = NEED_GUIDANCE
			state_transition = timeout
		break


	MONITORING:
		if certificate-is-expired or
		   (expiration-time-is-below-notify-threshold-value and
		    expiration-time-was-above-notify-threshold-value)
			update-template-values-based-on-cert
			state_next = NEED_TO_NOTIFY
			state_transition = now
		else
		if (expiration-time-is-below-renewal-threshold-value and
		    expiration-time-was-above-renewal-threshold-value)
			state_next = NEED_CSR
			state_transition = now
		else
			state_next = MONITORING
			state_transition = timeout
		break

	NEED_TO_NOTIFY:
		if starting-up
			state_next = MONITORING
			state_transition = now
		else
			start-notifying
			state_next = NOTIFYING
			state_transition = now
		break

	NOTIFYING:
		if starting-up
			state_next = NEED_TO_NOTIFY
			state_transition = now
		else
			if notification-completed
				if this-cert-gets-autorenew and
				   (expiration-time-is-below-renewal-threshold-value and
				    expiration-time-was-above-renewal-threshold-value)
					state_next = NEED_CSR
					state_transition = now
				else
					state_next = MONITORING
					state_transition = timeout
		break

	NEWLY_ADDED:
		if key-storage-is-known
			state_next = NEWLY_ADDED_START_READING_KEYINFO
			state_transition = now
		else
			state_next = NEWLY_ADDED_START_READING_CERT
			state_transition = now
		break

	NEWLY_ADDED_START_READING_KEYINFO:
		start-reading-key-information
		state_next = NEWLY_ADDED_READING_KEYINFO
		state_transition = now
		break

	NEWLY_ADDED_READING_KEYINFO:
		if starting-up
			state_next = NEWLY_ADDED_START_READING_KEYINFO
			state_transition = now
		else
			if finished-reading-key-information
				state_next = NEWLY_ADDED_START_READING_CERT
				state_transition = now
			elseif key-store-needs-token
				state_next = NEWLY_ADDED_NEED_KEYINFO_READ_TOKEN
				state_transition = now
			elseif key-store-needs-pin
				state_next = NEWLY_ADDED_NEED_KEYINFO_READ_PIN
				state_transition = now
			else
				state_next = NEWLY_ADDED_START_READING_CERT
				state_transition = now
		break

	NEWLY_ADDED_NEED_KEYINFO_READ_TOKEN:
		if starting-up
			state_next = NEWLY_ADDED_START_READING_KEYINFO
			state_transition = now
		break

	NEWLY_ADDED_NEED_KEYINFO_READ_PIN:
		if starting-up
			state_next = NEWLY_ADDED_START_READING_KEYINFO
			state_transition = now
		break

	NEWLY_ADDED_START_READING_CERT:
		start-reading-cert
		state_next = NEWLY_ADDED_READING_CERT
		state_transition = now
		break

	NEWLY_ADDED_READING_CERT:
		if starting-up
			state_next = NEWLY_ADDED_START_READING_CERT
			state_transition = now
		else
			if finished-reading-cert
				state_next = NEWLY_ADDED_DECIDING
				state_transition = now
		break

	NEWLY_ADDED_DECIDING:
		if entry-has-no-associated-ca
			try-to-set-ca-using-known-ca-list
		if we-have-a-cert
			state_next = MONITORING
			state_transition = now
		else
			if key-storage-is-known
				if key-is-present
					state_next = NEED_CSR
					state_transition = now
				else
					state_next = NEED_KEY_PAIR
					state_transition = now
			else
				state_next = NEED_GUIDANCE
				state_transition = now
		break

Types of actions and user guidance:
	Reenroll-from-scratch ("request -g"):
		state_next = NEED_KEY_PAIR
		state_transition = now
	Submit-key ("request", if no csr or arguments alter it):
		state_next = NEED_CSR
		state_transition = now
	Submit-csr (automatic for "request")
		state_next = HAVE_CSR
		state_transition = now
	Resubmit-csr (need to add "resubmit")
		state_next = HAVE_CSR
		state_transition = now
	Start-Tracking-with-AutoRenew ("start-tracking"):
		add-cert-to-monitoring-list
		state_next = MONITORING
		state_transition = now
	Start-Tracking-without-AutoRenew ("start-tracking"):
		add-cert-to-monitoring-list
		state_next = MONITORING
		state_transition = now
	Cancel ("stop-tracking"):
		remove-cert-from-monitoring-list
	Status ("list"):
		dump-monitoring-list

Data we need to track for each certificate/task/dbentry:
	* Type of key pair to generate [or use default settings]
	  default: RSA,2048
	* Location of key pair [use-once default]
	  default: NSS,/etc/pki/nssdb,,Server-Key-default
	* Location of certificate [use-once default]
	  default: NSS,/etc/pki/nssdb,,Server-Cert-default
	* Cached certificate issuer/serial/subject/spki/expiration/host/email
	* The last time we checked if expiration was imminent.
	* Interesting TTL values [or use default settings]
	  default: 30*24*60*60,7*24*60*60,3*24*60*60,2*24*60*60,1*24*60*60
	* How to notify administrator [or use default settings]
	  syslog(LOG_AUTHPRIV?) or mail to root@?
	* CSR template information [or imported from existing certificate]
	  * subject (cn=host name)
	  * SANs¹
	    * DNS
	    * email
	    * principal name
	  * ku¹, eku¹
	  ¹ Encoded as extensionRequest attributes.
	* Certificate State (state_current)
	* Whether to autorenew-at-expiration [or use default settings]
	* Whether to start monitoring at issue [or use default settings]
	* Type and location of CA [or use default settings]
	* Value of CA cookie for in-progress submissions.
	* Date of submission for in-progress submissions.