You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2021/04/08 02:02:58 UTC

[trafficcontrol] branch master updated: Refactor riak trafficvault interface (#5721)

This is an automated email from the ASF dual-hosted git repository.

ocket8888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 4e8e3ba  Refactor riak trafficvault interface (#5721)
4e8e3ba is described below

commit 4e8e3bab982e14db404c34a54ceb2e3fb0725c55
Author: Rawlin Peters <ra...@apache.org>
AuthorDate: Wed Apr 7 20:02:25 2021 -0600

    Refactor riak trafficvault interface (#5721)
    
    * asdf
    
    * Move riaksvc package into trafficvault/backends
    
    * Move riak implementation into trafficvault/backends/riaksvc
    
    * Privatize non-user-facing riaksvc functions
    
    * Move disabled backend into its own package
    
    * Add basic riak config validation, unit tests
    
    * Update docs
    
    * Add GoDoc comments
    
    * Add README.md for implementing TrafficVault backends
    
    * Add changelog entries
    
    * Add new options to example cdn.conf
    
    * Doc updates
    
    * Move godoc comment to actual definition
---
 CHANGELOG.md                                       |   8 +-
 docs/source/admin/traffic_ops.rst                  |  43 ++--
 docs/source/admin/traffic_vault.rst                |  68 +++--
 docs/source/development/traffic_ops.rst            |   2 +-
 docs/source/overview/traffic_vault.rst             |   4 +-
 lib/go-tc/deliveryservice_ssl_keys.go              |  19 +-
 traffic_ops/app/conf/cdn.conf                      |   2 +
 traffic_ops/traffic_ops_golang/api/api.go          |  32 ++-
 .../traffic_ops_golang/api/shared_handlers.go      |   4 -
 .../traffic_ops_golang/api/shared_handlers_test.go |  14 +-
 traffic_ops/traffic_ops_golang/cdn/dnssec.go       |  46 ++--
 .../traffic_ops_golang/cdn/dnssecrefresh.go        |  32 ++-
 traffic_ops/traffic_ops_golang/cdn/genksk.go       |  12 +-
 traffic_ops/traffic_ops_golang/cdn/sslkeys.go      |  21 +-
 traffic_ops/traffic_ops_golang/config/config.go    |  45 ++--
 .../traffic_ops_golang/config/config_test.go       |  51 ++--
 traffic_ops/traffic_ops_golang/crconfig/handler.go |   4 +-
 .../traffic_ops_golang/dbhelpers/db_helpers.go     |   6 +-
 .../traffic_ops_golang/deliveryservice/acme.go     |  18 +-
 .../deliveryservice/autorenewcerts.go              |  18 +-
 .../deliveryservice/deleteoldcerts.go              |  55 ++--
 .../deliveryservice/deliveryservices.go            |  12 +-
 .../traffic_ops_golang/deliveryservice/dnssec.go   |  23 +-
 .../traffic_ops_golang/deliveryservice/keys.go     |  39 +--
 .../deliveryservice/letsencryptcert.go             |  17 +-
 .../traffic_ops_golang/deliveryservice/sslkeys.go  |  16 +-
 .../traffic_ops_golang/deliveryservice/urlkey.go   |  33 ++-
 .../traffic_ops_golang/login/logout_test.go        |  32 ++-
 traffic_ops/traffic_ops_golang/ping/keys.go        |   3 +-
 traffic_ops/traffic_ops_golang/ping/riak.go        |   3 +-
 traffic_ops/traffic_ops_golang/ping/vault.go       |   3 +-
 .../traffic_ops_golang/profile/copy_test.go        |   5 +-
 traffic_ops/traffic_ops_golang/routing/routing.go  |  12 +-
 .../traffic_ops_golang/traffic_ops_golang.go       |  76 +++++-
 .../traffic_ops_golang/trafficvault/README.md      |  61 +++++
 .../trafficvault/backends/disabled/disabled.go     | 100 ++++++++
 .../{ => trafficvault/backends}/riaksvc/dsutil.go  | 280 +++++++++++----------
 .../trafficvault/backends/riaksvc/riak.go          | 128 ++++++++++
 .../backends}/riaksvc/riak_services.go             |  90 +++----
 .../backends}/riaksvc/riak_services_test.go        |  34 +--
 .../trafficvault/backends/riaksvc/riak_test.go     |  93 +++++++
 .../trafficvault/trafficvault.go                   | 112 +++++++++
 .../traffic_ops_golang/urisigning/urisigning.go    |  80 ++----
 .../urisigning/urisigning_test.go                  |   4 +-
 traffic_ops/traffic_ops_golang/vault/bucket.go     |  14 +-
 45 files changed, 1190 insertions(+), 584 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8a3639d..644627d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,10 +24,11 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - Added functionality to automatically renew ACME certificates.
 - Added ORT flag to set local.dns bind address from server service addresses
 - Added an endpoint for statuses on asynchronous jobs and applied it to the ACME renewal endpoint.
+- Added two new cdn.conf options to make Traffic Vault configuration more backend-agnostic: `traffic_vault_backend` and `traffic_vault_config`
 - Traffic Ops API version 4.0
 - `GET` request method for `/deliveryservices/{{ID}}/assign`
 - `GET` request method for `/deliveryservices/{{ID}}/status`
-- [#5644](https://github.com/apache/trafficcontrol/issues/5644) ORT config generation: Added ATS9 ip_allow.yaml support, and automatic generation if the server's package Parameter is 9.*
+- [#5644](https://github.com/apache/trafficcontrol/issues/5644) ORT config generation: Added ATS9 ip_allow.yaml support, and automatic generation if the server's package Parameter is 9.\*
 - t3c: Added option to track config changes in git.
 - ORT config generation: Added a rule to ip_allow such that PURGE requests are allowed over localhost
 
@@ -53,8 +54,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 - [apache/trafficcontrol](https://github.com/apache/trafficcontrol) is now a Go module
 - Updated Traffic Ops supported database version from PostgreSQL 9.6 to 13.2
 - Set Traffic Router to also accept TLSv1.3 protocols by default in server.xml
+- Refactored the Traffic Ops - Traffic Vault integration to more easily support the development of new Traffic Vault backends
 - Updated Apache Tomcat from 8.5.63 to 9.0.43
 
+### Deprecated
+- The `riak.conf` config file and its corresponding `--riakcfg` option in `traffic_ops_golang` have been deprecated. Please use `"traffic_vault_backend": "riak"` and `"traffic_vault_config"` (with the existing contents of riak.conf) instead.
+- The `riak_port` option in cdn.conf is now deprecated. Please use the `"port"` field in `traffic_vault_config` instead.
+
 ### Removed
 - The Perl implementation of Traffic Ops has been stripped out, along with the Go implementation's "fall-back to Perl" behavior.
 - The `compare` tool stack has been removed, as it no longer serves a purpose.
diff --git a/docs/source/admin/traffic_ops.rst b/docs/source/admin/traffic_ops.rst
index d54eab7..2b75c57 100644
--- a/docs/source/admin/traffic_ops.rst
+++ b/docs/source/admin/traffic_ops.rst
@@ -262,7 +262,7 @@ While this section contains instructions for running Traffic Ops manually, the o
 
 traffic_ops_golang
 ------------------
-``traffic_ops_golang [--version] [--plugins] [--api-routes] --cfg CONFIG_PATH --dbcfg DB_CONFIG_PATH --riakcfg TRAFFIC_VAULT_CONFIG_PATH``
+``traffic_ops_golang [--version] [--plugins] [--api-routes] --cfg CONFIG_PATH --dbcfg DB_CONFIG_PATH [--riakcfg RIAK_CONFIG_PATH]``
 
 .. option:: --cfg CONFIG_PATH
 
@@ -280,9 +280,10 @@ traffic_ops_golang
 
 	Print information about all API routes and exit. If also used with the :option:`--cfg` option, also print out the configured routing blacklist information from `cdn.conf`_.
 
-.. option:: --riakcfg TRAFFIC_VAULT_CONFIG_PATH
+.. option:: --riakcfg RIAK_CONFIG_PATH
 
-	This **mandatory** command line flag specifies the absolute or relative path to a configuration file used by Traffic Ops to establish connections to Traffic Vault - `riak.conf`_
+	.. deprecated:: 6.0
+		This optional command line flag specifies the absolute or relative path to a configuration file used by Traffic Ops to establish connections to Riak when used as the Traffic Vault backend - `riak.conf`_. Please use ``"traffic_vault_backend": "riak"`` and ``"traffic_vault_config": {...}`` (with the contents of `riak.conf`_) instead.
 
 	.. impl-detail:: The name of this flag is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.
 
@@ -372,12 +373,6 @@ This file deals with the configuration parameters of running Traffic Ops itself.
 	:pass_reset_path: A path to be added to ``base_url`` that is the URL of the UI's password reset interface. For Traffic Portal instances, this should always be set to "user".
 	:user_register_path: A path to be added to ``base_url`` that is the URL of the UI's new user registration interface. For Traffic Portal instances, this should always be set to "user".
 
-:riak_conf_path: An optional absolute or relative path to `riak.conf`_. If this field is not defined, is ``null``, or is an empty string (``""``), Traffic Ops will not be able to connect to Traffic Vault.
-
-	.. caution:: If Traffic Ops is unable to connect to Traffic Vault, many of its core features will not function. In particular, it will be impossible to create :term:`Delivery Services` that use HTTPS or DNSSEC.
-
-	.. impl-detail:: The name of this field is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.
-
 :secrets: This is an array of strings, which cannot be empty. The first secret in the array is used to encrypt Traffic Ops authentication cookies - multiple Traffic Ops instances serving the same CDN need to share secrets in order for users logged into one to be able to use their cookie as authentication with other instances.
 :smtp:    This optional section contains options for connecting to and authenticating with an :abbr:`SMTP (Simple Mail Transfer Protocol)` server for sending emails. If this section is undefined (or if ``enabled`` is explicitly ``false``), Traffic Ops will not be able to send emails and certain :ref:`to-api` endpoints that depend on that functionality will fail to operate.
 
@@ -443,6 +438,9 @@ This file deals with the configuration parameters of running Traffic Ops itself.
 	:request_timeout: An optional timeout in seconds that serves as the maximum time each Traffic Ops middleware can take to execute. If it is exceeded, the text "server timed out" is served in place of a response. If set to :code:`0`, :code:`60` is used instead. Default if not specified is :code:`60`.
 	:riak_port: An optional field that sets the port on which Traffic Ops will try to contact Traffic Vault for storage and retrieval of sensitive encryption keys.
 
+		.. deprecated:: 6.0
+			Please use a ``"port"`` field in ``traffic_vault_config`` instead when using ``"traffic_vault_backend": "riak"``.
+
 		.. impl-detail:: The name of this field is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.
 
 
@@ -452,6 +450,16 @@ This file deals with the configuration parameters of running Traffic Ops itself.
 
 	:write_timeout: An optional timeout in seconds set on handlers. After reading a request's header, the server will have this long to send back a response. If set to zero, there is no timeout. Default if not specified is zero.
 
+	:traffic_vault_backend:
+
+	    .. versionadded:: 6.0
+		    Optional. The name of which backend to use for Traffic Vault. Currently, the only supported backend is "riak".
+
+	:traffic_vault_config:
+
+	    .. versionadded:: 6.0
+		    Optional. The JSON configuration which is unique to the chosen Traffic Vault backend. See :ref:`traffic_vault_admin` for the configuration options for each supported backend.
+
 	.. _admin-routing-blacklist:
 
 	:routing_blacklist: Optional configuration for explicitly disabling any routes via ``disabled_routes``.
@@ -544,21 +552,12 @@ Example ldap.conf
 
 riak.conf
 """""""""
-This file sets authentication options for connections to Traffic Vault. `traffic_ops_golang`_ will look for this file at the path given by the value of the :option:`--riakcfg` flag as passed on startup. The contents of ``riak.conf`` are encoded as a JSON object, the keys of which are described below.
+.. deprecated:: 6.0
+	The ``riak.conf`` configuration file and associated :option:`--riakcfg` flag have been deprecated and will be removed from Traffic Control in the future. Please use ``"traffic_vault_backend": "riak"`` and put the existing contents of ``riak.conf`` into ``"traffic_vault_config": {...}`` in `cdn.conf`_ instead.
 
-.. impl-detail:: The name of this file is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.
-
-:password:      The password to use when authenticating with Traffic Vault
-:user:          The username to use when authenticating with Traffic Vault
-:MaxTLSVersion: Optional. This is the highest TLS version that Traffic Ops is allowed to use to connect to Traffic Vault. Valid values are "1.0", "1.1", "1.2", and "1.3". The default is "1.1".
+This file sets authentication options for connections to Riak when used as the Traffic Vault backend. `traffic_ops_golang`_ will look for this file at the path given by the value of the :option:`--riakcfg` flag as passed on startup. The contents of ``riak.conf`` are encoded as a JSON object, the keys of which are described in :ref:`traffic_vault_riak_backend`.
 
-.. note:: Enabling TLS 1.1 in Traffic Vault itself is required for Traffic Ops to communicate with Traffic Vault. See :ref:`Enabling TLS 1.1 <tv-admin-enable-tlsv1.1>` for details.
-
-Example riak.conf
-'''''''''''''''''
-.. include:: ../../../traffic_ops/app/conf/production/riak.conf
-	:code: json
-	:tab-width: 4
+.. impl-detail:: The name of this file is derived from the current database used in the implementation of Traffic Vault - `Riak KV <https://riak.com/products/riak-kv/index.html>`_.
 
 Installing the SSL Certificate
 ------------------------------
diff --git a/docs/source/admin/traffic_vault.rst b/docs/source/admin/traffic_vault.rst
index 720c7c5..cf275bf 100644
--- a/docs/source/admin/traffic_vault.rst
+++ b/docs/source/admin/traffic_vault.rst
@@ -13,19 +13,56 @@
 .. limitations under the License.
 ..
 
+.. _traffic_vault_admin:
+
 ****************************
 Traffic Vault Administration
 ****************************
-Installing Traffic Vault
-========================
+
+Currently, the only supported backend for Traffic Vault is Riak, but more backends may be supported in the future.
+
+.. _traffic_vault_riak_backend:
+
+Riak
+====
+
+In order to use the Riak backend for Traffic Vault, you will need to set the ``traffic_vault_backend`` option to ``"riak"`` and include the necessary configuration in the ``traffic_vault_config`` section in :file:`cdn.conf`. The ``traffic_vault_config`` options for the Riak backend are as follows:
+
+:password:      The password to use when authenticating with Riak
+:user:          The username to use when authenticating with Riak
+:port:          The Riak protobuf port to connect to. Default: 8087
+:tlsConfig:     Optional. Certain TLS options from `the tls.Config struct options <https://golang.org/pkg/crypto/tls/#Config>`_ may be included here, such as ``insecureSkipVerify: true`` to disable certificate validation in order to use self-signed certificates for test/development purposes.
+:MaxTLSVersion: Optional. This is the highest TLS version that Traffic Ops is allowed to use to connect to Traffic Vault. Valid values are "1.0", "1.1", "1.2", and "1.3". The default is "1.1".
+
+.. note:: Enabling TLS 1.1 in Riak itself is required for Traffic Ops to communicate with Riak. See :ref:`Enabling TLS 1.1 <tv-admin-enable-tlsv1.1>` for details.
+
+Example cdn.conf snippet:
+-------------------------
+
+.. code-block:: json
+
+	{
+		"traffic_ops_golang": {
+			"traffic_vault_backend": "riak",
+			"traffic_vault_config": {
+				"user": "riakuser",
+				"password": "password",
+				"MaxTLSVersion": "1.1",
+				"port": 8087
+			}
+		}
+	}
+
+Installing the Riak backend for Traffic Vault
+---------------------------------------------
 In order to successfully store private keys you will need to install Riak. The latest version of Riak can be downloaded on `the Riak website <https://docs.riak.com/riak/latest/downloads/>`_. The installation instructions for Riak can be found `here <https://docs.riak.com/riak/kv/latest/setup/installing/index.html>`__. Based on experience, version 2.0.5 of Riak is recommended, but the latest version should suffice.
 
-Configuring Traffic Vault
-=========================
-The following steps were taken to configure Riak in Comcast production environments.
+Configuring Riak
+----------------
+Follow these steps to configure Riak in a production environment.
 
 Self Signed Certificate configuration
--------------------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 .. note:: Self-signed certificates are not recommended for production use. Intended for development or learning purposes only. Modify subject as necessary.
 
 .. code-block:: shell
@@ -47,7 +84,7 @@ Self Signed Certificate configuration
 
 
 Riak Configuration File
------------------------
+^^^^^^^^^^^^^^^^^^^^^^^
 The following steps need to be performed on each Riak server in the cluster:
 
 #. Log into Riak server as root
@@ -74,7 +111,7 @@ Enabling TLS 1.1 (required)
 #. Consult the `Riak documentation <https://docs.riak.com/riak/kv/latest/setup/installing/verify/>`_ for instructions on how to verify the installed service
 
 ``riak-admin`` Configuration
-----------------------------
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 ``riak-admin`` is a command line utility used to configure Riak that needs to be run as root on a server in the Riak cluster.
 
 .. seealso:: `The riak-admin documentation <https://docs.riak.com/riak/kv/latest/using/admin/riak-admin/>`_
@@ -89,9 +126,8 @@ Enabling TLS 1.1 (required)
 	riak-admin security add-group admins
 	riak-admin security add-group keysusers
 
-	# User name and password should be stored in
-	# /opt/traffic_ops/app/conf/<environment>/riak.conf on the Traffic Ops
-	# server
+	# User name and password should be stored in the traffic_vault_config section in
+	# /opt/traffic_ops/app/conf/cdn.conf on the Traffic Ops server (with traffic_vault_backend = riak)
 	# In this example, we assume the usernames 'admin' and 'riakuser' with
 	# respective passwords stored in the ADMIN_PASSWORD and RIAK_USER_PASSWORD
 	# environment variables
@@ -113,15 +149,15 @@ Enabling TLS 1.1 (required)
 
 
 Traffic Ops Configuration
--------------------------
-Before a fully set-up Traffic Vault instance may be used, it must be added as a server to Traffic Ops. The easiest way to accomplish this is via Traffic Portal at :menuselection:`Configure --> Servers`, though :ref:`to-api-servers` may also be used by low-level tools and/or scripts. The Traffic Ops configuration file :file:`/opt/traffic_ops/app/conf/{environment}/riak.conf` for the appropriate environment must also be updated to reflect the correct username and password for accessing the [...]
+^^^^^^^^^^^^^^^^^^^^^^^^^
+Before a fully set-up Riak instance may be used as the Traffic Vault backend, it must be added as a server to Traffic Ops. The easiest way to accomplish this is via Traffic Portal at :menuselection:`Configure --> Servers`, though :ref:`to-api-servers` may also be used by low-level tools and/or scripts. The Traffic Ops configuration file :file:`/opt/traffic_ops/app/conf/cdn.conf` must be updated to set ``traffic_vault_backend`` to ``"riak"`` and the ``traffic_vault_config`` to include the [...]
 
 Configuring Riak Search
-=======================
-In order to more effectively support retrieval of SSL certificates by Traffic Router and :term:`ORT`, Traffic Vault uses `Riak search <https://docs.riak.com/riak/kv/latest/using/reference/search/>`_. Riak Search uses `Apache Solr <https://lucene.apache.org/solr>`_ for indexing and searching of records. This section explains how to enable, configure, and validate Riak Search.
+-----------------------
+In order to more effectively support retrieval of SSL certificates by Traffic Router and :term:`ORT`, the Riak backend for Traffic Vault uses `Riak search <https://docs.riak.com/riak/kv/latest/using/reference/search/>`_. Riak Search uses `Apache Solr <https://lucene.apache.org/solr>`_ for indexing and searching of records. This section explains how to enable, configure, and validate Riak Search.
 
 Riak Configuration
-------------------
+^^^^^^^^^^^^^^^^^^
 On each Traffic Vault server follow these steps.
 
 #. If Java (JDKv1.8+) is not already installed on your Riak server, install Java
diff --git a/docs/source/development/traffic_ops.rst b/docs/source/development/traffic_ops.rst
index 1c18efe..9adb978 100644
--- a/docs/source/development/traffic_ops.rst
+++ b/docs/source/development/traffic_ops.rst
@@ -161,7 +161,7 @@ Traffic Ops Project Tree Overview
 		- config/ - Defines configuration structures and methods for reading them in from files
 		- dbhelpers/ - Assorted utilities that provide functionality for common database tasks, e.g. "Get a user by email"
 		- plugin/ - The Traffic Ops plugin system, with examples
-		- riaksvc/ - In addition to handling routes that deal with storing secrets in or retrieving secrets from Traffic Vault, this package provides a library of functions for interacting with Traffic Vault for other handlers to use.
+		- trafficvault/ - This package provides the Traffic Vault interface and associated backend implementations for other handlers to interact with Traffic Vault.
 		- routing/ - Contains logic for mapping all of the :ref:`to-api` endpoints to their handlers, as well as proxying requests back to the Perl implementation and managing plugins, and also provides some wrappers around registered handlers that set common HTTP headers and connection options
 		- swaggerdocs/ A currently abandoned attempt at defining the :ref:`to-api` using `Swagger <https://swagger.io/>`_ - it may be picked up again at some point in the (distant) future
 		- tenant/ - Contains utilities for dealing with :term:`Tenantable <Tenant>` resources, particularly for checking for permissions
diff --git a/docs/source/overview/traffic_vault.rst b/docs/source/overview/traffic_vault.rst
index b622c59..0e7a63c 100644
--- a/docs/source/overview/traffic_vault.rst
+++ b/docs/source/overview/traffic_vault.rst
@@ -18,7 +18,7 @@
 *************
 Traffic Vault
 *************
-Traffic Vault is a key/value store used for storing the following types of information:
+Traffic Vault is a data store used for storing the following types of sensitive information:
 
 * SSL Certificates
 
@@ -40,6 +40,6 @@ Traffic Vault is a key/value store used for storing the following types of infor
 
 * URL Signing Keys
 
-As the name suggests, Traffic Vault is meant to be a "vault" of private keys that only certain users are allowed to access. In order to create, add, and retrieve keys a user must have administrative privileges. Keys can be created via the :ref:`tp-overview` UI, but they can only be retrieved via the :ref:`to-api`. The keystore used by Traffic Vault is `Riak <http://basho.com/products/riak-kv/>`_. :ref:`to-overview` accesses Riak via HTTPS on port 8088. :ref:`to-overview` uses Riak's REST [...]
+As the name suggests, Traffic Vault is meant to be a "vault" of private keys that only certain users are allowed to access. In order to create, add, and retrieve keys a user must have administrative privileges. Keys can be created via the :ref:`tp-overview` UI, but they can only be retrieved via the :ref:`to-api`. Currently, the only supported data store used by Traffic Vault is `Riak <http://basho.com/products/riak-kv/>`_. :ref:`to-overview` accesses Riak via HTTPS on port 8088. :ref:`t [...]
 
 .. seealso:: Information on the Riak API can be found in `their documentation <http://docs.riak.com/riak/latest/dev/references/http/>`_.
diff --git a/lib/go-tc/deliveryservice_ssl_keys.go b/lib/go-tc/deliveryservice_ssl_keys.go
index 9662694..be91837 100644
--- a/lib/go-tc/deliveryservice_ssl_keys.go
+++ b/lib/go-tc/deliveryservice_ssl_keys.go
@@ -23,6 +23,8 @@ import (
 	"time"
 
 	"github.com/apache/trafficcontrol/lib/go-util"
+
+	"github.com/lestrrat/go-jwx/jwk"
 )
 
 const DNSSECKSKType = "ksk"
@@ -201,7 +203,16 @@ func checkNilOrEmpty(s *string) bool {
 	return s == nil || *s == ""
 }
 
-type RiakPingResp struct {
+// URISignerKeyset is the container for the CDN URI signing keys.
+type URISignerKeyset struct {
+	RenewalKid *string               `json:"renewal_kid"`
+	Keys       []jwk.EssentialHeader `json:"keys"`
+}
+
+// Deprecated: use TrafficVaultPingResponse instead.
+type RiakPingResp TrafficVaultPingResponse
+
+type TrafficVaultPingResponse struct {
 	Status string `json:"status"`
 	Server string `json:"server"`
 }
@@ -209,10 +220,12 @@ type RiakPingResp struct {
 // DNSSECKeys is the DNSSEC keys as stored in Riak, plus the DS record text.
 type DNSSECKeys map[string]DNSSECKeySet
 
-// DNSSECKeysV11 is the DNSSEC keys object stored in Riak. The map key strings are both DeliveryServiceNames and CDNNames.
-
+// Deprecated: use DNSSECKeysTrafficVault instead
 type DNSSECKeysRiak DNSSECKeysV11
 
+type DNSSECKeysTrafficVault DNSSECKeysV11
+
+// DNSSECKeysV11 is the DNSSEC keys object stored in Riak. The map key strings are both DeliveryServiceNames and CDNNames.
 type DNSSECKeysV11 map[string]DNSSECKeySetV11
 
 type DNSSECKeySet struct {
diff --git a/traffic_ops/app/conf/cdn.conf b/traffic_ops/app/conf/cdn.conf
index 9535c43..d3f04b6 100644
--- a/traffic_ops/app/conf/cdn.conf
+++ b/traffic_ops/app/conf/cdn.conf
@@ -34,6 +34,8 @@
         },
         "whitelisted_oauth_urls": [],
         "oauth_client_secret": "",
+        "traffic_vault_backend": "",
+        "traffic_vault_config": {},
         "routing_blacklist": {
             "ignore_unknown_routes": false,
             "disabled_routes": []
diff --git a/traffic_ops/traffic_ops_golang/api/api.go b/traffic_ops/traffic_ops_golang/api/api.go
index 8c5cc12..2c0f55c 100644
--- a/traffic_ops/traffic_ops_golang/api/api.go
+++ b/traffic_ops/traffic_ops_golang/api/api.go
@@ -45,6 +45,8 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tocookie"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled"
 
 	influx "github.com/influxdata/influxdb/client/v2"
 	"github.com/jmoiron/sqlx"
@@ -71,10 +73,12 @@ const ResourceModifiedError = errorConstant("resource was modified since the tim
 
 // Common context.Context value keys.
 const (
-	DBContextKey      = "db"
-	ConfigContextKey  = "context"
-	ReqIDContextKey   = "reqid"
-	APIRespWrittenKey = "respwritten"
+	DBContextKey           = "db"
+	ConfigContextKey       = "context"
+	ReqIDContextKey        = "reqid"
+	APIRespWrittenKey      = "respwritten"
+	PathParamsKey          = "pathParams"
+	TrafficVaultContextKey = "tv"
 )
 
 const influxServersQuery = `
@@ -488,6 +492,7 @@ type APIInfo struct {
 	ReqID     uint64
 	Version   *Version
 	Tx        *sqlx.Tx
+	Vault     trafficvault.TrafficVault
 	Config    *config.Config
 	request   *http.Request
 }
@@ -530,6 +535,10 @@ func NewInfo(r *http.Request, requiredParams []string, intParamNames []string) (
 	if err != nil {
 		return &APIInfo{Tx: &sqlx.Tx{}}, errors.New("getting config: " + err.Error()), nil, http.StatusInternalServerError
 	}
+	tv, err := GetTrafficVault(r.Context())
+	if err != nil {
+		return &APIInfo{Tx: &sqlx.Tx{}}, errors.New("getting TrafficVault: " + err.Error()), nil, http.StatusInternalServerError
+	}
 	reqID, err := getReqID(r.Context())
 	if err != nil {
 		return &APIInfo{Tx: &sqlx.Tx{}}, errors.New("getting reqID: " + err.Error()), nil, http.StatusInternalServerError
@@ -557,6 +566,7 @@ func NewInfo(r *http.Request, requiredParams []string, intParamNames []string) (
 		IntParams: intParams,
 		User:      user,
 		Tx:        tx,
+		Vault:     tv,
 		request:   r,
 	}, nil, nil, http.StatusOK
 }
@@ -820,6 +830,20 @@ func GetConfig(ctx context.Context) (*config.Config, error) {
 	return nil, errors.New("No config found in Context")
 }
 
+func GetTrafficVault(ctx context.Context) (trafficvault.TrafficVault, error) {
+	val := ctx.Value(TrafficVaultContextKey)
+	if val != nil {
+		switch v := val.(type) {
+		case trafficvault.TrafficVault:
+			return v, nil
+		default:
+			return nil, fmt.Errorf("TrafficVault found with bad type: %T", v)
+		}
+	}
+	// this return should never be reached because a non-nil TrafficVault should always be included in the request context
+	return &disabled.Disabled{}, errors.New("no Traffic Vault found in Context")
+}
+
 func getReqID(ctx context.Context) (uint64, error) {
 	val := ctx.Value(ReqIDContextKey)
 	if val != nil {
diff --git a/traffic_ops/traffic_ops_golang/api/shared_handlers.go b/traffic_ops/traffic_ops_golang/api/shared_handlers.go
index f56b6a0..4aa5c0f 100644
--- a/traffic_ops/traffic_ops_golang/api/shared_handlers.go
+++ b/traffic_ops/traffic_ops_golang/api/shared_handlers.go
@@ -36,10 +36,6 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 )
 
-const PathParamsKey = "pathParams"
-const DBKey = "db"
-const ConfigKey = "cfg"
-
 type KeyFieldInfo struct {
 	Field string
 	Func  func(string) (interface{}, error)
diff --git a/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go b/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
index 508881d..2a26e18 100644
--- a/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
+++ b/traffic_ops/traffic_ops_golang/api/shared_handlers_test.go
@@ -32,8 +32,10 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-rfc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-	"github.com/jmoiron/sqlx"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled"
 
+	"github.com/jmoiron/sqlx"
 	sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
 )
 
@@ -136,6 +138,8 @@ func TestCreateHandler(t *testing.T) {
 	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
 	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
 	ctx = context.WithValue(ctx, PathParamsKey, map[string]string{"id": "1"})
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, TrafficVaultContextKey, tv)
 
 	// Add our context to the request
 	r = r.WithContext(ctx)
@@ -182,6 +186,8 @@ func TestReadHandler(t *testing.T) {
 	ctx = context.WithValue(ctx, DBContextKey, db)
 	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
 	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, TrafficVaultContextKey, tv)
 
 	// Add our context to the request
 	r = r.WithContext(ctx)
@@ -225,6 +231,8 @@ func TestReadHandlerIMS(t *testing.T) {
 	ctx = context.WithValue(ctx, DBContextKey, db)
 	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
 	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, TrafficVaultContextKey, tv)
 	futureTime := time.Now().AddDate(0, 0, 1)
 	time := futureTime.Format(time.RFC1123)
 	r.Header.Add(rfc.IfModifiedSince, time)
@@ -268,6 +276,8 @@ func TestUpdateHandler(t *testing.T) {
 	ctx = context.WithValue(ctx, DBContextKey, db)
 	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
 	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, TrafficVaultContextKey, tv)
 
 	// Add our context to the request
 	r = r.WithContext(ctx)
@@ -315,6 +325,8 @@ func TestDeleteHandler(t *testing.T) {
 	ctx = context.WithValue(ctx, DBContextKey, db)
 	ctx = context.WithValue(ctx, ConfigContextKey, &cfg)
 	ctx = context.WithValue(ctx, ReqIDContextKey, uint64(0))
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, TrafficVaultContextKey, tv)
 	// Add our context to the request
 	r = r.WithContext(ctx)
 
diff --git a/traffic_ops/traffic_ops_golang/cdn/dnssec.go b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
index b91d3d4..d77ab31 100644
--- a/traffic_ops/traffic_ops_golang/cdn/dnssec.go
+++ b/traffic_ops/traffic_ops_golang/cdn/dnssec.go
@@ -31,10 +31,9 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 )
 
 const CDNDNSSECKeyType = "dnssec"
@@ -48,6 +47,11 @@ func CreateDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting CDN DNSSEC keys from Traffic Vault: Traffic Vault is not configured"))
+		return
+	}
+
 	req := tc.CDNDNSSECGenerateReq{}
 	if err := api.Parse(r.Body, inf.Tx.Tx, &req); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("parsing request: "+err.Error()), nil)
@@ -77,7 +81,7 @@ func CreateDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if err := generateStoreDNSSECKeys(inf.Tx.Tx, inf.Config, cdnName, cdnDomain, uint64(*req.TTL), uint64(*req.KSKExpirationDays), uint64(*req.ZSKExpirationDays), int64(*req.EffectiveDateUnix)); err != nil {
+	if err := generateStoreDNSSECKeys(inf.Tx.Tx, cdnName, cdnDomain, uint64(*req.TTL), uint64(*req.KSKExpirationDays), uint64(*req.ZSKExpirationDays), int64(*req.EffectiveDateUnix), inf.Vault); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("generating and storing DNSSEC CDN keys: "+err.Error()))
 		return
 	}
@@ -102,9 +106,14 @@ func GetDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting CDN DNSSEC keys from Traffic Vault: Traffic Vault is not configured"))
+		return
+	}
+
 	cdnName := inf.Params["name"]
 
-	riakKeys, keysExist, err := riaksvc.GetDNSSECKeys(cdnName, inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	tvKeys, keysExist, err := inf.Vault.GetDNSSECKeys(cdnName, inf.Tx.Tx)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting DNSSEC CDN keys: "+err.Error()))
 		return
@@ -122,9 +131,9 @@ func GetDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 		dsTTL = DefaultDSTTL
 	}
 
-	keys, err := deliveryservice.MakeDNSSECKeysFromRiakKeys(riakKeys, dsTTL)
+	keys, err := deliveryservice.MakeDNSSECKeysFromTrafficVaultKeys(tvKeys, dsTTL)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("creating DNSSEC keys object from Riak keys: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("creating DNSSEC keys object from Traffic Vault keys: "+err.Error()))
 		return
 	}
 	api.WriteResp(w, r, keys)
@@ -139,7 +148,7 @@ func GetDNSSECKeysV11(w http.ResponseWriter, r *http.Request) {
 	defer inf.Close()
 
 	cdnName := inf.Params["name"]
-	riakKeys, keysExist, err := riaksvc.GetDNSSECKeys(cdnName, inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	riakKeys, keysExist, err := inf.Vault.GetDNSSECKeys(cdnName, inf.Tx.Tx)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting DNSSEC CDN keys: "+err.Error()))
 		return
@@ -162,20 +171,20 @@ func GetDSRecordTTL(tx *sql.Tx, cdn string) (time.Duration, error) {
 
 func generateStoreDNSSECKeys(
 	tx *sql.Tx,
-	cfg *config.Config,
 	cdnName string,
 	cdnDomain string,
 	ttlSeconds uint64,
 	kExpDays uint64,
 	zExpDays uint64,
 	effectiveDateUnix int64,
+	tv trafficvault.TrafficVault,
 ) error {
 
 	zExp := time.Duration(zExpDays) * time.Hour * 24
 	kExp := time.Duration(kExpDays) * time.Hour * 24
 	ttl := time.Duration(ttlSeconds) * time.Second
 
-	oldKeys, oldKeysExist, err := riaksvc.GetDNSSECKeys(cdnName, tx, cfg.RiakAuthOptions, cfg.RiakPort)
+	oldKeys, oldKeysExist, err := tv.GetDNSSECKeys(cdnName, tx)
 	if err != nil {
 		return errors.New("getting old dnssec keys: " + err.Error())
 	}
@@ -223,7 +232,7 @@ func generateStoreDNSSECKeys(
 		}
 	}
 
-	newKeys := tc.DNSSECKeysV11{}
+	newKeys := tc.DNSSECKeysTrafficVault{}
 	newKeys[cdnName] = tc.DNSSECKeySetV11{ZSK: newCDNZSKs, KSK: newCDNKSKs}
 
 	cdnKeys := newKeys[cdnName]
@@ -249,14 +258,14 @@ func generateStoreDNSSECKeys(
 		exampleURLs := deliveryservice.MakeExampleURLs(ds.Protocol, ds.Type, ds.RoutingName, matchlist, cdnDomain)
 		log.Infoln("Creating keys for " + ds.Name)
 		overrideTTL := true
-		dsKeys, err := deliveryservice.CreateDNSSECKeys(tx, cfg, ds.Name, exampleURLs, cdnKeys, kExp, zExp, ttl, overrideTTL)
+		dsKeys, err := deliveryservice.CreateDNSSECKeys(exampleURLs, cdnKeys, kExp, zExp, ttl, overrideTTL)
 		if err != nil {
 			return errors.New("creating delivery service DNSSEC keys: " + err.Error())
 		}
 		newKeys[ds.Name] = dsKeys
 	}
-	if err := riaksvc.PutDNSSECKeys(tc.DNSSECKeysRiak(newKeys), cdnName, tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-		return errors.New("putting Riak DNSSEC CDN keys: " + err.Error())
+	if err := tv.PutDNSSECKeys(cdnName, newKeys, tx); err != nil {
+		return errors.New("putting CDN DNSSEC keys in Traffic Vault: " + err.Error())
 	}
 	return nil
 }
@@ -325,9 +334,8 @@ func deleteDNSSECKeys(w http.ResponseWriter, r *http.Request, deprecated bool) {
 	}
 	defer inf.Close()
 
-	cluster, err := riaksvc.GetPooledCluster(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
-	if err != nil {
-		writeError(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting riak cluster: "+err.Error()), deprecated)
+	if !inf.Config.TrafficVaultEnabled {
+		writeError(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting CDN DNSSEC keys from Traffic Vault: Traffic Vault is not configured"), deprecated)
 		return
 	}
 
@@ -340,11 +348,11 @@ func deleteDNSSECKeys(w http.ResponseWriter, r *http.Request, deprecated bool) {
 		writeError(w, r, inf.Tx.Tx, http.StatusNotFound, nil, nil, deprecated)
 		return
 	}
-
-	if err := riaksvc.DeleteObject(key, CDNDNSSECKeyType, cluster); err != nil {
-		writeError(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting cdn dnssec keys: "+err.Error()), deprecated)
+	if err := inf.Vault.DeleteDNSSECKeys(key, inf.Tx.Tx); err != nil {
+		writeError(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting CDN DNSSEC keys: "+err.Error()), deprecated)
 		return
 	}
+
 	api.CreateChangeLogRawTx(api.ApiChange, "CDN: "+key+", ID: "+strconv.Itoa(cdnID)+", ACTION: Deleted DNSSEC keys", inf.User, inf.Tx.Tx)
 	successMsg := "Successfully deleted " + CDNDNSSECKeyType + " for " + key
 	if deprecated {
diff --git a/traffic_ops/traffic_ops_golang/cdn/dnssecrefresh.go b/traffic_ops/traffic_ops_golang/cdn/dnssecrefresh.go
index bd9f032..503dc12 100644
--- a/traffic_ops/traffic_ops_golang/cdn/dnssecrefresh.go
+++ b/traffic_ops/traffic_ops_golang/cdn/dnssecrefresh.go
@@ -32,9 +32,8 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 
 	"github.com/lib/pq"
 )
@@ -54,6 +53,17 @@ func RefreshDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 			unsetInDNSSECKeyRefresh()
 			return
 		}
+		if !cfg.TrafficVaultEnabled {
+			api.HandleErr(w, r, noTx, http.StatusInternalServerError, nil, errors.New("refreshing DNSSEC keys: Traffic Vault not enabled"))
+			unsetInDNSSECKeyRefresh()
+			return
+		}
+		tv, err := api.GetTrafficVault(r.Context())
+		if err != nil {
+			api.HandleErr(w, r, noTx, http.StatusInternalServerError, nil, errors.New("RefresHDNSSECKeys getting Traffic Vault from context: "+err.Error()))
+			unsetInDNSSECKeyRefresh()
+			return
+		}
 
 		tx, err := db.Begin()
 		if err != nil {
@@ -61,7 +71,7 @@ func RefreshDNSSECKeys(w http.ResponseWriter, r *http.Request) {
 			unsetInDNSSECKeyRefresh()
 			return
 		}
-		go doDNSSECKeyRefresh(tx, cfg) // doDNSSECKeyRefresh takes ownership of tx and MUST close it.
+		go doDNSSECKeyRefresh(tx, tv) // doDNSSECKeyRefresh takes ownership of tx and MUST close it.
 	} else {
 		log.Infoln("RefreshDNSSECKeys called, while server was concurrently executing a refresh, doing nothing")
 	}
@@ -78,7 +88,7 @@ const DNSSECKeyRefreshDefaultZSKExpiration = time.Duration(30) * time.Hour * 24
 // doDNSSECKeyRefresh refreshes the CDN's DNSSEC keys, as necessary.
 // This takes ownership of tx, and MUST call `tx.Close()`.
 // This SHOULD only be called if setInDNSSECKeyRefresh() returned true, in which case this MUST call unsetInDNSSECKeyRefresh() before returning.
-func doDNSSECKeyRefresh(tx *sql.Tx, cfg *config.Config) {
+func doDNSSECKeyRefresh(tx *sql.Tx, tv trafficvault.TrafficVault) {
 	doCommit := true
 	defer func() {
 		if doCommit {
@@ -127,13 +137,13 @@ func doDNSSECKeyRefresh(tx *sql.Tx, cfg *config.Config) {
 	}
 
 	for _, cdnInf := range cdnDNSSECKeyParams {
-		keys, ok, err := riaksvc.GetDNSSECKeys(string(cdnInf.CDNName), tx, cfg.RiakAuthOptions, cfg.RiakPort) // TODO get all in a map beforehand
+		keys, ok, err := tv.GetDNSSECKeys(string(cdnInf.CDNName), tx) // TODO get all in a map beforehand
 		if err != nil {
-			log.Warnln("refreshing DNSSEC Keys: getting cdn '" + string(cdnInf.CDNName) + "' keys from Riak, skipping: " + err.Error())
+			log.Warnln("refreshing DNSSEC Keys: getting cdn '" + string(cdnInf.CDNName) + "' keys from Traffic Vault, skipping: " + err.Error())
 			continue
 		}
 		if !ok {
-			log.Warnln("refreshing DNSSEC Keys: cdn '" + string(cdnInf.CDNName) + "' has no keys in Riak, skipping")
+			log.Warnln("refreshing DNSSEC Keys: cdn '" + string(cdnInf.CDNName) + "' has no keys in Traffic Vault, skipping")
 			continue
 		}
 
@@ -202,12 +212,12 @@ func doDNSSECKeyRefresh(tx *sql.Tx, cfg *config.Config) {
 
 				cdnKeys, ok := keys[string(ds.CDNName)]
 				if !ok {
-					log.Errorln("refreshing DNSSEC Keys: cdn has no keys, cannot create ds keys: " + err.Error())
+					log.Errorln("refreshing DNSSEC Keys: cdn has no keys, cannot create ds keys")
 					continue
 				}
 
 				overrideTTL := false
-				dsKeys, err := deliveryservice.CreateDNSSECKeys(tx, cfg, string(ds.DSName), exampleURLs[ds.DSName], cdnKeys, defaultKSKExpiration, defaultZSKExpiration, ttl, overrideTTL)
+				dsKeys, err := deliveryservice.CreateDNSSECKeys(exampleURLs[ds.DSName], cdnKeys, defaultKSKExpiration, defaultZSKExpiration, ttl, overrideTTL)
 				if err != nil {
 					log.Errorln("refreshing DNSSEC Keys: creating missing ds keys: " + err.Error())
 				}
@@ -261,8 +271,8 @@ func doDNSSECKeyRefresh(tx *sql.Tx, cfg *config.Config) {
 			}
 		}
 		if updatedAny {
-			if err := riaksvc.PutDNSSECKeys(keys, string(cdnInf.CDNName), tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-				log.Errorln("refreshing DNSSEC Keys: putting keys into Riak for cdn '" + string(cdnInf.CDNName) + "': " + err.Error())
+			if err := tv.PutDNSSECKeys(string(cdnInf.CDNName), keys, tx); err != nil {
+				log.Errorln("refreshing DNSSEC Keys: putting keys into Traffic Vault for cdn '" + string(cdnInf.CDNName) + "': " + err.Error())
 			}
 		}
 	}
diff --git a/traffic_ops/traffic_ops_golang/cdn/genksk.go b/traffic_ops/traffic_ops_golang/cdn/genksk.go
index a62c9b6..987b869 100644
--- a/traffic_ops/traffic_ops_golang/cdn/genksk.go
+++ b/traffic_ops/traffic_ops_golang/cdn/genksk.go
@@ -31,7 +31,6 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/deliveryservice"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 )
 
 const DefaultKSKTTLSeconds = 60
@@ -47,6 +46,11 @@ func GenerateKSK(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("generating CDN KSK: Traffic Vault is not configured"))
+		return
+	}
+
 	cdnName := tc.CDNName(inf.Params["name"])
 	req := tc.CDNGenerateKSKReq{}
 	if err := api.Parse(r.Body, inf.Tx.Tx, &req); err != nil {
@@ -87,13 +91,13 @@ func GenerateKSK(w http.ResponseWriter, r *http.Request) {
 		multiplier = &mult
 	}
 
-	dnssecKeys, ok, err := riaksvc.GetDNSSECKeys(string(cdnName), inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	dnssecKeys, ok, err := inf.Vault.GetDNSSECKeys(string(cdnName), inf.Tx.Tx)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting CDN DNSSEC keys: "+err.Error()))
 		return
 	}
 	if !ok {
-		log.Warnln("Generating CDN '" + string(cdnName) + "' KSK: no keys found in Riak, generating and inserting new key anyway")
+		log.Warnln("Generating CDN '" + string(cdnName) + "' KSK: no keys found in Traffic Vault, generating and inserting new key anyway")
 	}
 
 	isKSK := true
@@ -105,7 +109,7 @@ func GenerateKSK(w http.ResponseWriter, r *http.Request) {
 	}
 	dnssecKeys[string(cdnName)] = newKey
 
-	if err := riaksvc.PutDNSSECKeys(dnssecKeys, string(cdnName), inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort); err != nil {
+	if err := inf.Vault.PutDNSSECKeys(string(cdnName), dnssecKeys, inf.Tx.Tx); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("putting CDN DNSSEC keys: "+err.Error()))
 		return
 	}
diff --git a/traffic_ops/traffic_ops_golang/cdn/sslkeys.go b/traffic_ops/traffic_ops_golang/cdn/sslkeys.go
index 95252ac..a14be70 100644
--- a/traffic_ops/traffic_ops_golang/cdn/sslkeys.go
+++ b/traffic_ops/traffic_ops_golang/cdn/sslkeys.go
@@ -20,15 +20,10 @@ package cdn
  */
 
 import (
-	"database/sql"
 	"errors"
 	"net/http"
 
-	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
-
-	"github.com/basho/riak-go-client"
 )
 
 func GetSSLKeys(w http.ResponseWriter, r *http.Request) {
@@ -38,18 +33,14 @@ func GetSSLKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	defer inf.Close()
-	keys, err := getSSLKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, inf.Params["name"])
-	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting cdn ssl keys: "+err.Error()))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting CDN SSL keys from Traffic Vault: Traffic Vault is not configured"))
 		return
 	}
-	api.WriteResp(w, r, keys)
-}
-
-func getSSLKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdnName string) ([]tc.CDNSSLKey, error) {
-	keys, err := riaksvc.GetCDNSSLKeysObj(tx, authOpts, riakPort, cdnName)
+	keys, err := inf.Vault.GetCDNSSLKeys(inf.Params["name"], inf.Tx.Tx)
 	if err != nil {
-		return nil, errors.New("getting cdn ssl keys from Riak: " + err.Error())
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting cdn ssl keys from Traffic Vault: "+err.Error()))
+		return
 	}
-	return keys, nil
+	api.WriteResp(w, r, keys)
 }
diff --git a/traffic_ops/traffic_ops_golang/config/config.go b/traffic_ops/traffic_ops_golang/config/config.go
index 1810677..5c3c48f 100644
--- a/traffic_ops/traffic_ops_golang/config/config.go
+++ b/traffic_ops/traffic_ops_golang/config/config.go
@@ -33,8 +33,6 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-rfc"
 	"github.com/apache/trafficcontrol/lib/go-util"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
-	"github.com/basho/riak-go-client"
 )
 
 // Config reflects the structure of the cdn.conf file
@@ -52,17 +50,15 @@ type Config struct {
 	AcmeAccounts           []ConfigAcmeAccount `json:"acme_accounts"`
 	DB                     ConfigDatabase      `json:"db"`
 	Secrets                []string            `json:"secrets"`
-	// NOTE: don't care about any other fields for now..
-	RiakAuthOptions  *riak.AuthOptions
-	RiakEnabled      bool
-	ConfigLDAP       *ConfigLDAP
-	LDAPEnabled      bool
-	LDAPConfPath     string `json:"ldap_conf_location"`
-	ConfigInflux     *ConfigInflux
-	InfluxEnabled    bool
-	InfluxDBConfPath string `json:"influxdb_conf_path"`
-	Version          string
-	UseIMS           bool `json:"use_ims"`
+	TrafficVaultEnabled    bool
+	ConfigLDAP             *ConfigLDAP
+	LDAPEnabled            bool
+	LDAPConfPath           string `json:"ldap_conf_location"`
+	ConfigInflux           *ConfigInflux
+	InfluxEnabled          bool
+	InfluxDBConfPath       string `json:"influxdb_conf_path"`
+	Version                string
+	UseIMS                 bool `json:"use_ims"`
 }
 
 // ConfigHypnotoad carries http setting for hypnotoad (mojolicious) server
@@ -101,12 +97,15 @@ type ConfigTrafficOpsGolang struct {
 	PluginSharedConfig       map[string]interface{}     `json:"plugin_shared_config"`
 	ProfilingEnabled         bool                       `json:"profiling_enabled"`
 	ProfilingLocation        string                     `json:"profiling_location"`
-	RiakPort                 *uint                      `json:"riak_port"`
-	WhitelistedOAuthUrls     []string                   `json:"whitelisted_oauth_urls"`
-	OAuthClientSecret        string                     `json:"oauth_client_secret"`
-	RoutingBlacklist         `json:"routing_blacklist"`
-	SupportedDSMetrics       []string    `json:"supported_ds_metrics"`
-	TLSConfig                *tls.Config `json:"tls_config"`
+	// Deprecated: use 'port' in traffic_vault_config instead.
+	RiakPort             *uint    `json:"riak_port"`
+	WhitelistedOAuthUrls []string `json:"whitelisted_oauth_urls"`
+	OAuthClientSecret    string   `json:"oauth_client_secret"`
+	RoutingBlacklist     `json:"routing_blacklist"`
+	SupportedDSMetrics   []string        `json:"supported_ds_metrics"`
+	TLSConfig            *tls.Config     `json:"tls_config"`
+	TrafficVaultBackend  string          `json:"traffic_vault_backend"`
+	TrafficVaultConfig   json.RawMessage `json:"traffic_vault_config"`
 
 	// CRConfigUseRequestHost is whether to use the client request host header in the CRConfig. If false, uses the tm.url parameter.
 	// This defaults to false. Traffic Ops used to always use the host header, setting this true will resume that legacy behavior.
@@ -263,7 +262,7 @@ func LoadCdnConfig(cdnConfPath string) (Config, error) {
 
 // LoadConfig - reads the config file into the Config struct
 
-func LoadConfig(cdnConfPath string, dbConfPath string, riakConfPath string, appVersion string) (Config, []error, bool) {
+func LoadConfig(cdnConfPath string, dbConfPath string, appVersion string) (Config, []error, bool) {
 	// load cdn.conf
 	cfg, err := LoadCdnConfig(cdnConfPath)
 	if err != nil {
@@ -285,12 +284,6 @@ func LoadConfig(cdnConfPath string, dbConfPath string, riakConfPath string, appV
 		return Config{}, []error{fmt.Errorf("parsing config '%s': %v", cdnConfPath, err)}, BlockStartup
 	}
 
-	if riakConfPath != "" {
-		cfg.RiakEnabled, cfg.RiakAuthOptions, err = riaksvc.GetRiakConfig(riakConfPath)
-		if err != nil {
-			return Config{}, []error{fmt.Errorf("parsing config '%s': %v", riakConfPath, err)}, BlockStartup
-		}
-	}
 	// check for and load ldap.conf
 	if cfg.LDAPConfPath != "" {
 		cfg.LDAPEnabled, cfg.ConfigLDAP, err = GetLDAPConfig(cfg.LDAPConfPath)
diff --git a/traffic_ops/traffic_ops_golang/config/config_test.go b/traffic_ops/traffic_ops_golang/config/config_test.go
index 9fe1682..bfb5d27 100644
--- a/traffic_ops/traffic_ops_golang/config/config_test.go
+++ b/traffic_ops/traffic_ops_golang/config/config_test.go
@@ -20,17 +20,13 @@ package config
  */
 
 import (
-	"crypto/tls"
+	"encoding/json"
 	"flag"
 	"fmt"
 	"io/ioutil"
 	"os"
-	"reflect"
 	"strings"
 	"testing"
-
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
-	"github.com/basho/riak-go-client"
 )
 
 const (
@@ -116,6 +112,10 @@ const (
 			"ignore_unknown_routes": true,
 			"disabled_routes": [4, 5, 6]
 		},
+		"traffic_vault_backend": "something",
+		"traffic_vault_config": {
+			"foo": "bar"
+		},
 		"log_location_error": "stderr",
 		"log_location_warning": "stdout",
 		"log_location_info": "stdout",
@@ -157,17 +157,6 @@ const (
 	"type": "Pg"
 }
 `
-
-	goodRiakConfig = `
-	   {
-	       "user": "riakuser",
-	       "password": "password",
-	       "MaxTLSVersion": "1.1",
-	       "tlsConfig": {
-	           "insecureSkipVerify": true
-	       }
-	   }
-	   	`
 )
 
 func TestLoadConfig(t *testing.T) {
@@ -195,14 +184,8 @@ func TestLoadConfig(t *testing.T) {
 	}
 	defer os.Remove(goodDbCfg) // clean up
 
-	goodRiakCfg, err := tempFileWith([]byte(goodRiakConfig))
-	if err != nil {
-		t.Errorf("cannot create temp file: %v", err)
-	}
-	defer os.Remove(goodRiakCfg) // clean up
-
 	// test bad paths
-	_, errs, blockStartup := LoadConfig(badPath, badPath, badPath, version)
+	_, errs, blockStartup := LoadConfig(badPath, badPath, version)
 	exp = fmt.Sprintf("Loading cdn config from '%s'", badPath)
 	if !strings.HasPrefix(errs[0].Error(), exp) {
 		t.Error("expected", exp, "got", errs[0].Error())
@@ -212,7 +195,7 @@ func TestLoadConfig(t *testing.T) {
 	}
 
 	// bad json in cdn.conf
-	_, errs, blockStartup = LoadConfig(badCfg, badCfg, badPath, version)
+	_, errs, blockStartup = LoadConfig(badCfg, badCfg, version)
 	exp = fmt.Sprintf("Loading cdn config from '%s': unmarshalling '%s'", badCfg, badCfg)
 	if !strings.HasPrefix(errs[0].Error(), exp) {
 		t.Error("expected", exp, "got", errs[0].Error())
@@ -222,7 +205,7 @@ func TestLoadConfig(t *testing.T) {
 	}
 
 	// good cdn.conf, bad db conf
-	_, errs, blockStartup = LoadConfig(goodCfg, badPath, badPath, version)
+	_, errs, blockStartup = LoadConfig(goodCfg, badPath, version)
 	exp = fmt.Sprintf("reading db conf '%s'", badPath)
 	if !strings.HasPrefix(errs[0].Error(), exp) {
 		t.Error("expected", exp, "got", errs[0].Error())
@@ -232,7 +215,7 @@ func TestLoadConfig(t *testing.T) {
 	}
 
 	// good cdn.conf,  bad json in database.conf
-	_, errs, blockStartup = LoadConfig(goodCfg, badCfg, badPath, version)
+	_, errs, blockStartup = LoadConfig(goodCfg, badCfg, version)
 	exp = fmt.Sprintf("unmarshalling '%s'", badCfg)
 	if !strings.HasPrefix(errs[0].Error(), exp) {
 		t.Error("expected", exp, "got", errs[0].Error())
@@ -242,7 +225,7 @@ func TestLoadConfig(t *testing.T) {
 	}
 
 	// good cdn.conf,  good database.conf
-	cfg, errs, blockStartup = LoadConfig(goodCfg, goodDbCfg, goodRiakCfg, version)
+	cfg, errs, blockStartup = LoadConfig(goodCfg, goodDbCfg, version)
 	if len(errs) != 0 {
 		t.Error("Good config -- unexpected errors: ", errs)
 	}
@@ -250,10 +233,16 @@ func TestLoadConfig(t *testing.T) {
 		t.Error("expected blockStartup to be false but it was ", blockStartup)
 	}
 
-	expectedRiak := riaksvc.TOAuthOptions{AuthOptions: riak.AuthOptions{User: "riakuser", Password: "password", TlsConfig: &tls.Config{InsecureSkipVerify: true, MaxVersion: tls.VersionTLS11}}}
-
-	if cfg.RiakAuthOptions.User != expectedRiak.User || cfg.RiakAuthOptions.Password != expectedRiak.Password || !reflect.DeepEqual(cfg.RiakAuthOptions.TlsConfig, expectedRiak.TlsConfig) {
-		t.Error(fmt.Printf("Error parsing riak conf expected: %++v but got: %++v\n", expectedRiak, cfg.RiakAuthOptions))
+	if cfg.TrafficVaultBackend != "something" {
+		t.Errorf("expected traffic_vault_backend to be 'something', actual: '%s'", cfg.TrafficVaultBackend)
+	}
+	tvConfig := make(map[string]string)
+	err = json.Unmarshal(cfg.TrafficVaultConfig, &tvConfig)
+	if err != nil {
+		t.Errorf("unmarshalling traffic_vault_config - expected: no error, actual: %s", err.Error())
+	}
+	if tvConfig["foo"] != "bar" {
+		t.Errorf("unmarshalling traffic_vault_config - expected: foo = bar, actual: foo = %s", tvConfig["foo"])
 	}
 
 	if *debugLogging {
diff --git a/traffic_ops/traffic_ops_golang/crconfig/handler.go b/traffic_ops/traffic_ops_golang/crconfig/handler.go
index 0118e6a..3a85e54 100644
--- a/traffic_ops/traffic_ops_golang/crconfig/handler.go
+++ b/traffic_ops/traffic_ops_golang/crconfig/handler.go
@@ -241,7 +241,7 @@ func snapshotHandler(w http.ResponseWriter, r *http.Request, deprecated bool) {
 		return
 	}
 
-	if err := deliveryservice.DeleteOldCerts(db.DB, inf.Tx.Tx, inf.Config, tc.CDNName(cdn)); err != nil {
+	if err := deliveryservice.DeleteOldCerts(db.DB, inf.Tx.Tx, inf.Config, tc.CDNName(cdn), inf.Vault); err != nil {
 		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New(r.RemoteAddr+" snapshotting CRConfig and Monitoring: starting old certificate deletion job: "+err.Error()), deprecated, &alt)
 		return
 	}
@@ -293,7 +293,7 @@ func SnapshotOldGUIHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if err := deliveryservice.DeleteOldCerts(db.DB, inf.Tx.Tx, inf.Config, tc.CDNName(cdn)); err != nil {
+	if err := deliveryservice.DeleteOldCerts(db.DB, inf.Tx.Tx, inf.Config, tc.CDNName(cdn), inf.Vault); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New(r.RemoteAddr+" old snapshotting CRConfig and Monitoring: starting old certificate deletion job: "+err.Error()))
 		return
 	}
diff --git a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
index 6999fea..390d03a 100644
--- a/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
+++ b/traffic_ops/traffic_ops_golang/dbhelpers/db_helpers.go
@@ -779,8 +779,8 @@ func GetServerInfo(serverID int, tx *sql.Tx) (tc.ServerInfo, bool, error) {
 	return servers[0], true, nil
 }
 
-func GetCDNDSes(tx *sql.Tx, cdn tc.CDNName) (map[tc.DeliveryServiceName]struct{}, error) {
-	dses := map[tc.DeliveryServiceName]struct{}{}
+func GetCDNDSes(tx *sql.Tx, cdn tc.CDNName) (map[string]struct{}, error) {
+	dses := map[string]struct{}{}
 	qry := `SELECT xml_id from deliveryservice where cdn_id = (select id from cdn where name = $1)`
 	rows, err := tx.Query(qry, cdn)
 	if err != nil {
@@ -789,7 +789,7 @@ func GetCDNDSes(tx *sql.Tx, cdn tc.CDNName) (map[tc.DeliveryServiceName]struct{}
 	defer rows.Close()
 
 	for rows.Next() {
-		ds := tc.DeliveryServiceName("")
+		ds := ""
 		if err := rows.Scan(&ds); err != nil {
 			return nil, errors.New("scanning: " + err.Error())
 		}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/acme.go b/traffic_ops/traffic_ops_golang/deliveryservice/acme.go
index 30cdb49..cb0ec75 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/acme.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/acme.go
@@ -36,8 +36,8 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 
 	"github.com/go-acme/lego/certcrypto"
 	"github.com/go-acme/lego/certificate"
@@ -57,8 +57,8 @@ func RenewAcmeCertificate(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	defer inf.Close()
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.RenewAcmeCertificate: Traffic Vault is not configured"))
 		return
 	}
 	xmlID := inf.Params["xmlid"]
@@ -70,7 +70,7 @@ func RenewAcmeCertificate(w http.ResponseWriter, r *http.Request) {
 
 	ctx, _ := context.WithTimeout(r.Context(), LetsEncryptTimeout)
 
-	userErr, sysErr, statusCode := renewAcmeCerts(inf.Config, xmlID, ctx, inf.User)
+	userErr, sysErr, statusCode := renewAcmeCerts(inf.Config, xmlID, ctx, inf.User, inf.Vault)
 	if userErr != nil || sysErr != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, statusCode, userErr, sysErr)
 	}
@@ -79,7 +79,7 @@ func RenewAcmeCertificate(w http.ResponseWriter, r *http.Request) {
 
 }
 
-func renewAcmeCerts(cfg *config.Config, dsName string, ctx context.Context, currentUser *auth.CurrentUser) (error, error, int) {
+func renewAcmeCerts(cfg *config.Config, dsName string, ctx context.Context, currentUser *auth.CurrentUser, tv trafficvault.TrafficVault) (error, error, int) {
 	db, err := api.GetDB(ctx)
 	if err != nil {
 		log.Errorf(dsName+": Error getting db: %s", err.Error())
@@ -120,7 +120,7 @@ func renewAcmeCerts(cfg *config.Config, dsName string, ctx context.Context, curr
 	if cfg == nil {
 		return nil, errors.New("acme: config was nil"), http.StatusInternalServerError
 	}
-	keyObj, ok, err := riaksvc.GetDeliveryServiceSSLKeysObjV15(dsName, strconv.Itoa(int(*certVersion)), tx, cfg.RiakAuthOptions, cfg.RiakPort)
+	keyObj, ok, err := tv.GetDeliveryServiceSSLKeys(dsName, strconv.Itoa(int(*certVersion)), tx)
 	if err != nil {
 		return nil, errors.New("getting ssl keys for xmlId: " + dsName + " and version: " + strconv.Itoa(int(*certVersion)) + " : " + err.Error()), http.StatusInternalServerError
 	}
@@ -169,10 +169,10 @@ func renewAcmeCerts(cfg *config.Config, dsName string, ctx context.Context, curr
 		CSR: string(EncodePEMToLegacyPerlRiakFormat([]byte("ACME Generated"))),
 	}
 
-	if err := riaksvc.PutDeliveryServiceSSLKeysObj(newCertObj, tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-		log.Errorf("Error posting acme certificate to riak: %s", err.Error())
+	if err := tv.PutDeliveryServiceSSLKeys(newCertObj, tx); err != nil {
+		log.Errorf("Error putting acme certificate in Traffic Vault: %s", err.Error())
 		api.CreateChangeLogRawTx(api.ApiChange, "DS: "+dsName+", ID: "+strconv.Itoa(*dsID)+", ACTION: FAILED to add SSL keys with "+acmeAccount.AcmeProvider, currentUser, logTx)
-		return nil, errors.New(dsName + ": putting riak keys: " + err.Error()), http.StatusInternalServerError
+		return nil, errors.New(dsName + ": putting keys in Traffic Vault: " + err.Error()), http.StatusInternalServerError
 	}
 
 	tx2, err := db.Begin()
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go b/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
index d04683a..c7f27a7 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/autorenewcerts.go
@@ -33,7 +33,7 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 )
 
 type DsKey struct {
@@ -80,8 +80,8 @@ func renewCertificates(w http.ResponseWriter, r *http.Request, deprecated bool)
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, errors.New("the Riak service is unavailable"), errors.New("getting SSL keys from Riak by xml id: Riak is not configured"), deprecated, deprecation)
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, errors.New("the Traffic Vault service is unavailable"), errors.New("getting SSL keys from Traffic Vault by xml id: Traffic Vault is not configured"), deprecated, deprecation)
 		return
 	}
 
@@ -109,7 +109,7 @@ func renewCertificates(w http.ResponseWriter, r *http.Request, deprecated bool)
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 	}
 
-	go RunAutorenewal(existingCerts, inf.Config, ctx, inf.User, asyncStatusId)
+	go RunAutorenewal(existingCerts, inf.Config, ctx, inf.User, asyncStatusId, inf.Vault)
 
 	var alerts tc.Alerts
 	if deprecated {
@@ -125,7 +125,7 @@ func renewCertificates(w http.ResponseWriter, r *http.Request, deprecated bool)
 	api.WriteAlerts(w, r, http.StatusAccepted, alerts)
 
 }
-func RunAutorenewal(existingCerts []ExistingCerts, cfg *config.Config, ctx context.Context, currentUser *auth.CurrentUser, asyncStatusId int) {
+func RunAutorenewal(existingCerts []ExistingCerts, cfg *config.Config, ctx context.Context, currentUser *auth.CurrentUser, asyncStatusId int, tv trafficvault.TrafficVault) {
 	db, err := api.GetDB(ctx)
 	if err != nil {
 		log.Errorf("Error getting db: %s", err.Error())
@@ -164,7 +164,7 @@ func RunAutorenewal(existingCerts []ExistingCerts, cfg *config.Config, ctx conte
 		}
 
 		dsExpInfo := DsExpirationInfo{}
-		keyObj, ok, err := riaksvc.GetDeliveryServiceSSLKeysObjV15(ds.XmlId, strconv.Itoa(int(ds.Version.Int64)), tx, cfg.RiakAuthOptions, cfg.RiakPort)
+		keyObj, ok, err := tv.GetDeliveryServiceSSLKeys(ds.XmlId, strconv.Itoa(int(ds.Version.Int64)), tx)
 		if err != nil {
 			log.Errorf("getting ssl keys for xmlId: %s and version: %d : %s", ds.XmlId, ds.Version.Int64, err.Error())
 			dsExpInfo.XmlId = ds.XmlId
@@ -229,8 +229,8 @@ func RunAutorenewal(existingCerts []ExistingCerts, cfg *config.Config, ctx conte
 				},
 			}
 
-			if error := GetLetsEncryptCertificates(cfg, req, ctx, currentUser); error != nil {
-				dsExpInfo.Error = error
+			if err := GetLetsEncryptCertificates(cfg, req, ctx, currentUser, tv); err != nil {
+				dsExpInfo.Error = err
 				errorCount++
 			} else {
 				renewedCount++
@@ -244,7 +244,7 @@ func RunAutorenewal(existingCerts []ExistingCerts, cfg *config.Config, ctx conte
 			if acmeAccount == nil {
 				keysFound.OtherExpirations = append(keysFound.OtherExpirations, dsExpInfo)
 			} else {
-				userErr, sysErr, statusCode := renewAcmeCerts(cfg, keyObj.DeliveryService, ctx, currentUser)
+				userErr, sysErr, statusCode := renewAcmeCerts(cfg, keyObj.DeliveryService, ctx, currentUser, tv)
 				if userErr != nil {
 					errorCount++
 					dsExpInfo.Error = userErr
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deleteoldcerts.go b/traffic_ops/traffic_ops_golang/deliveryservice/deleteoldcerts.go
index 9447908..478c43b 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deleteoldcerts.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deleteoldcerts.go
@@ -23,7 +23,6 @@ import (
 	"context"
 	"database/sql"
 	"errors"
-	"strings"
 	"sync"
 	"time"
 
@@ -31,9 +30,7 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
-
-	"github.com/basho/riak-go-client"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 )
 
 // DeleteOldCerts asynchronously deletes HTTPS certificates in Riak which have no corresponding delivery service in the database.
@@ -46,9 +43,9 @@ import (
 //
 // If certificate deletion is already being processed by a goroutine, another delete will be queued, and this immediately returns nil. Only one delete will ever be queued.
 //
-func DeleteOldCerts(db *sql.DB, tx *sql.Tx, cfg *config.Config, cdn tc.CDNName) error {
-	if !cfg.RiakEnabled {
-		log.Infoln("deleting old delivery service certificates: Riak is not enabled, returning without cleaning up old certificates.")
+func DeleteOldCerts(db *sql.DB, tx *sql.Tx, cfg *config.Config, cdn tc.CDNName, tv trafficvault.TrafficVault) error {
+	if !cfg.TrafficVaultEnabled {
+		log.Infoln("deleting old delivery service certificates: Traffic Vault is not enabled, returning without cleaning up old certificates.")
 		return nil
 	}
 	if db == nil {
@@ -57,48 +54,26 @@ func DeleteOldCerts(db *sql.DB, tx *sql.Tx, cfg *config.Config, cdn tc.CDNName)
 	if cfg == nil {
 		return errors.New("nil config")
 	}
-	startOldCertDeleter(db, tx, time.Duration(cfg.DBQueryTimeoutSeconds)*time.Second, cfg.RiakAuthOptions, cfg.RiakPort, cdn)
+	startOldCertDeleter(db, tx, time.Duration(cfg.DBQueryTimeoutSeconds)*time.Second, cdn, tv)
 	cleanupOldCertDeleters(tx)
 	return nil
 }
 
 // deleteOldDSCerts deletes the HTTPS certificates in Riak of delivery services which have been deleted in Traffic Ops.
-func deleteOldDSCerts(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName) error {
-	dsKeys, err := riaksvc.GetCDNSSLKeysDSNames(tx, authOpts, riakPort, cdn)
-	if err != nil {
-		return errors.New("getting riak ds keys: " + err.Error())
-	}
-
+func deleteOldDSCerts(tx *sql.Tx, cdn tc.CDNName, tv trafficvault.TrafficVault) error {
 	dses, err := dbhelpers.GetCDNDSes(tx, cdn)
 	if err != nil {
 		return errors.New("getting ds names: " + err.Error())
 	}
 
-	successes := []string{}
-	failures := []string{}
-	for ds, riakKeys := range dsKeys {
-		if _, ok := dses[ds]; ok {
-			continue
-		}
-		for _, riakKey := range riakKeys {
-			err := riaksvc.DeleteDeliveryServicesSSLKey(tx, authOpts, riakPort, riakKey)
-			if err != nil {
-				log.Errorln("deleting Riak SSL keys for Delivery Service '" + string(ds) + "' key '" + riakKey + "': " + err.Error())
-				failures = append(failures, string(ds))
-			} else {
-				log.Infoln("Deleted Riak SSL keys for delivery service which has been deleted in the database '" + string(ds) + "' key '" + riakKey + "'")
-				successes = append(successes, string(ds))
-			}
-		}
-	}
-	if len(failures) > 0 {
-		return errors.New("successfully deleted Riak SSL keys for deleted dses [" + strings.Join(successes, ", ") + "], but failed to delete Riak SSL keys for [" + strings.Join(failures, ", ") + "]; see the error log for details")
+	if err := tv.DeleteOldDeliveryServiceSSLKeys(dses, string(cdn), tx); err != nil {
+		return errors.New("getting ds keys from Traffic Vault: " + err.Error())
 	}
 	return nil
 }
 
 // deleteOldDSCertsDB takes a db, and creates a transaction to pass to deleteOldDSCerts.
-func deleteOldDSCertsDB(db *sql.DB, dbTimeout time.Duration, riakOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName) {
+func deleteOldDSCertsDB(db *sql.DB, dbTimeout time.Duration, cdn tc.CDNName, tv trafficvault.TrafficVault) {
 	dbCtx, cancelTx := context.WithTimeout(context.Background(), dbTimeout)
 	tx, err := db.BeginTx(dbCtx, nil)
 	if err != nil {
@@ -108,7 +83,7 @@ func deleteOldDSCertsDB(db *sql.DB, dbTimeout time.Duration, riakOpts *riak.Auth
 	defer cancelTx()
 	txCommit := false
 	defer dbhelpers.CommitIf(tx, &txCommit)
-	if err := deleteOldDSCerts(tx, riakOpts, riakPort, cdn); err != nil {
+	if err := deleteOldDSCerts(tx, cdn, tv); err != nil {
 		log.Errorln("deleting old DS certificates: " + err.Error())
 		return
 	}
@@ -123,10 +98,10 @@ type OldCertDeleters struct {
 }
 
 // startOldCertDeleter tells the old cert deleter goroutine to start another delete job, creating the goroutine if it doesn't exist.
-func startOldCertDeleter(db *sql.DB, tx *sql.Tx, dbTimeout time.Duration, riakOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName) {
+func startOldCertDeleter(db *sql.DB, tx *sql.Tx, dbTimeout time.Duration, cdn tc.CDNName, tv trafficvault.TrafficVault) {
 	oldCertDeleter := getOrCreateOldCertDeleter(cdn)
 	oldCertDeleter.Once.Do(func() {
-		go doOldCertDeleter(oldCertDeleter.Start, oldCertDeleter.Die, db, dbTimeout, riakOpts, riakPort, cdn)
+		go doOldCertDeleter(oldCertDeleter.Start, oldCertDeleter.Die, db, dbTimeout, cdn, tv)
 	})
 
 	select {
@@ -185,16 +160,16 @@ func newOldCertDeleter() *OldCertDeleter {
 	}
 }
 
-func doOldCertDeleter(do chan struct{}, die chan struct{}, db *sql.DB, dbTimeout time.Duration, riakOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName) {
+func doOldCertDeleter(do chan struct{}, die chan struct{}, db *sql.DB, dbTimeout time.Duration, cdn tc.CDNName, tv trafficvault.TrafficVault) {
 	for {
 		select {
 		case <-do:
-			deleteOldDSCertsDB(db, dbTimeout, riakOpts, riakPort, cdn)
+			deleteOldDSCertsDB(db, dbTimeout, cdn, tv)
 		case <-die:
 			// Go selects aren't ordered, so double-check the do chan in case a race happened and a job came in at the same time as the die.
 			select {
 			case <-do:
-				deleteOldDSCertsDB(db, dbTimeout, riakOpts, riakPort, cdn)
+				deleteOldDSCertsDB(db, dbTimeout, cdn, tv)
 			default:
 			}
 			return
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
index b89370a..9e4424e 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/deliveryservices.go
@@ -24,9 +24,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
-	"github.com/asaskevich/govalidator"
-	validation "github.com/go-ozzo/ozzo-validation"
 	"net/http"
 	"regexp"
 	"strconv"
@@ -35,6 +32,7 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
@@ -42,6 +40,8 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/util/ims"
 
+	"github.com/asaskevich/govalidator"
+	validation "github.com/go-ozzo/ozzo-validation"
 	"github.com/jmoiron/sqlx"
 	"github.com/lib/pq"
 )
@@ -332,7 +332,6 @@ func createV31(w http.ResponseWriter, r *http.Request, inf *api.APIInfo, dsV31 t
 func createV40(w http.ResponseWriter, r *http.Request, inf *api.APIInfo, dsV40 tc.DeliveryServiceV40) (*tc.DeliveryServiceV40, int, error, error) {
 	user := inf.User
 	tx := inf.Tx.Tx
-	cfg := inf.Config
 	ds := tc.DeliveryServiceV4(dsV40)
 	if err := Validate(tx, &ds); err != nil {
 		return nil, http.StatusBadRequest, errors.New("invalid request: " + err.Error()), nil
@@ -480,7 +479,10 @@ func createV40(w http.ResponseWriter, r *http.Request, inf *api.APIInfo, dsV40 t
 	}
 
 	if dnssecEnabled && ds.Type.UsesDNSSECKeys() {
-		if userErr, sysErr, statusCode := PutDNSSecKeys(tx, cfg, *ds.XMLID, cdnName, ds.ExampleURLs); userErr != nil || sysErr != nil {
+		if !inf.Config.TrafficVaultEnabled {
+			return nil, http.StatusInternalServerError, nil, errors.New("cannot create DNSSEC keys for delivery service: Traffic Vault is not configured")
+		}
+		if userErr, sysErr, statusCode := PutDNSSecKeys(tx, *ds.XMLID, cdnName, ds.ExampleURLs, inf.Vault); userErr != nil || sysErr != nil {
 			return nil, statusCode, userErr, sysErr
 		}
 	}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/dnssec.go b/traffic_ops/traffic_ops_golang/deliveryservice/dnssec.go
index 94852a1..fbd9096 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/dnssec.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/dnssec.go
@@ -30,16 +30,15 @@ import (
 	"time"
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 
 	"github.com/miekg/dns"
 )
 
-func PutDNSSecKeys(tx *sql.Tx, cfg *config.Config, xmlID string, cdnName string, exampleURLs []string) (error, error, int) {
-	keys, ok, err := riaksvc.GetDNSSECKeys(cdnName, tx, cfg.RiakAuthOptions, cfg.RiakPort)
+func PutDNSSecKeys(tx *sql.Tx, xmlID string, cdnName string, exampleURLs []string, tv trafficvault.TrafficVault) (error, error, int) {
+	keys, ok, err := tv.GetDNSSECKeys(cdnName, tx)
 	if err != nil {
-		return nil, errors.New("getting DNSSec keys from Riak: " + err.Error()), http.StatusInternalServerError
+		return nil, errors.New("getting DNSSec keys from Traffic Vault: " + err.Error()), http.StatusInternalServerError
 	} else if !ok {
 		return fmt.Errorf("there are no DNSSec keys for the CDN %s which is required to create keys for the deliveryservice", cdnName), nil, http.StatusBadRequest
 	}
@@ -51,24 +50,24 @@ func PutDNSSecKeys(tx *sql.Tx, cfg *config.Config, xmlID string, cdnName string,
 	kExp := getKeyExpiration(cdnKeys.KSK, dnssecDefaultKSKExpiration)
 	zExp := getKeyExpiration(cdnKeys.ZSK, dnssecDefaultZSKExpiration)
 	overrideTTL := false
-	dsKeys, err := CreateDNSSECKeys(tx, cfg, xmlID, exampleURLs, cdnKeys, kExp, zExp, dnssecDefaultTTL, overrideTTL)
+	dsKeys, err := CreateDNSSECKeys(exampleURLs, cdnKeys, kExp, zExp, dnssecDefaultTTL, overrideTTL)
 	if err != nil {
 		return nil, errors.New("creating DNSSEC keys for delivery service '" + xmlID + "': " + err.Error()), http.StatusInternalServerError
 	}
 	keys[xmlID] = dsKeys
-	if err := riaksvc.PutDNSSECKeys(keys, cdnName, tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-		return nil, errors.New("putting Riak DNSSEC keys: " + err.Error()), http.StatusInternalServerError
+	if err := tv.PutDNSSECKeys(cdnName, keys, tx); err != nil {
+		return nil, errors.New("putting DNSSEC keys in Traffic Vault: " + err.Error()), http.StatusInternalServerError
 	}
 	return nil, nil, http.StatusOK
 }
 
 // CreateDNSSECKeys creates DNSSEC keys for the given delivery service, updating existing keys if they exist. The overrideTTL parameter determines whether to reuse existing key TTLs if they exist, or to override existing TTLs with the ttl parameter's value.
-func CreateDNSSECKeys(tx *sql.Tx, cfg *config.Config, xmlID string, exampleURLs []string, cdnKeys tc.DNSSECKeySetV11, kskExpiration time.Duration, zskExpiration time.Duration, ttl time.Duration, overrideTTL bool) (tc.DNSSECKeySetV11, error) {
+func CreateDNSSECKeys(exampleURLs []string, cdnKeys tc.DNSSECKeySetV11, kskExpiration time.Duration, zskExpiration time.Duration, ttl time.Duration, overrideTTL bool) (tc.DNSSECKeySetV11, error) {
 	if len(cdnKeys.ZSK) == 0 {
-		return tc.DNSSECKeySetV11{}, errors.New("getting DNSSec keys from Riak: no DNSSec ZSK keys for CDN")
+		return tc.DNSSECKeySetV11{}, errors.New("getting DNSSec keys from Traffic Vault: no DNSSec ZSK keys for CDN")
 	}
 	if len(cdnKeys.KSK) == 0 {
-		return tc.DNSSECKeySetV11{}, errors.New("getting DNSSec keys from Riak: no DNSSec ZSK keys for CDN")
+		return tc.DNSSECKeySetV11{}, errors.New("getting DNSSec keys from Traffic Vault: no DNSSec ZSK keys for CDN")
 	}
 	if !overrideTTL {
 		ttl = getKeyTTL(cdnKeys.KSK, ttl)
@@ -208,7 +207,7 @@ func getKeyTTL(keys []tc.DNSSECKeyV11, defaultTTL time.Duration) time.Duration {
 
 // MakeDNSSECKeySetFromRiakKeySet creates a DNSSECKeySet (as served by Traffic Ops) from a DNSSECKeysRiak (as stored in Riak), adding any computed data.
 // Notably, this adds the full DS Record text to CDN KSKs
-func MakeDNSSECKeysFromRiakKeys(riakKeys tc.DNSSECKeysRiak, dsTTL time.Duration) (tc.DNSSECKeys, error) {
+func MakeDNSSECKeysFromTrafficVaultKeys(riakKeys tc.DNSSECKeysTrafficVault, dsTTL time.Duration) (tc.DNSSECKeys, error) {
 	keys := map[string]tc.DNSSECKeySet{}
 	for name, riakKeySet := range riakKeys {
 		newKeySet := tc.DNSSECKeySet{}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
index d7e8c4e..2ba7c0a 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/keys.go
@@ -37,8 +37,8 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 )
 
 const (
@@ -54,8 +54,8 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	defer inf.Close()
-	if !inf.Config.RiakEnabled {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("adding SSL keys to Riak for delivery service: Riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("adding SSL keys to Traffic Vault for delivery service: Traffic Vault is not configured"))
 		return
 	}
 	req := tc.DeliveryServiceAddSSLKeysReq{}
@@ -109,8 +109,8 @@ func AddSSLKeys(w http.ResponseWriter, r *http.Request) {
 		AuthType:        authType,
 	}
 
-	if err := riaksvc.PutDeliveryServiceSSLKeysObj(dsSSLKeys, inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort); err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("putting SSL keys in Riak for delivery service '"+*req.DeliveryService+"': "+err.Error()))
+	if err := inf.Vault.PutDeliveryServiceSSLKeys(dsSSLKeys, inf.Tx.Tx); err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("putting SSL keys in Traffic Vault for delivery service '"+*req.DeliveryService+"': "+err.Error()))
 		return
 	}
 	if err := updateSSLKeyVersion(*req.DeliveryService, req.Version.ToInt64(), inf.Tx.Tx); err != nil {
@@ -141,7 +141,7 @@ func GetSSLKeysByHostName(w http.ResponseWriter, r *http.Request) {
 	if err != nil {
 		return
 	}
-	getSSLKeysByXMLIDHelper(xmlID, tc.CreateAlerts(tc.WarnLevel, hostnameKeyDepMsg), inf, w, r)
+	getSSLKeysByXMLIDHelper(xmlID, inf.Vault, tc.CreateAlerts(tc.WarnLevel, hostnameKeyDepMsg), inf, w, r)
 }
 
 func getXmlIDFromRequest(w http.ResponseWriter, r *http.Request) (*api.APIInfo, string, error) {
@@ -154,8 +154,8 @@ func getXmlIDFromRequest(w http.ResponseWriter, r *http.Request) (*api.APIInfo,
 		return inf, "", errors.New("getting XML ID from request")
 	}
 
-	if inf.Config.RiakEnabled == false {
-		userErr = api.LogErr(r, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Riak by host name: Riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		userErr = api.LogErr(r, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Traffic Vault by host name: Traffic Vault is not configured"))
 		alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
 		api.WriteAlerts(w, r, http.StatusInternalServerError, alerts)
 		return inf, "", errors.New("getting XML ID from request")
@@ -225,15 +225,15 @@ func GetSSLKeysByXMLID(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	defer inf.Close()
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Riak by xml id: Riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Traffic Vault by xml id: Traffic Vault is not configured"))
 		return
 	}
 	xmlID := inf.Params["xmlid"]
-	getSSLKeysByXMLIDHelper(xmlID, tc.Alerts{}, inf, w, r)
+	getSSLKeysByXMLIDHelper(xmlID, inf.Vault, tc.Alerts{}, inf, w, r)
 }
 
-func getSSLKeysByXMLIDHelper(xmlID string, alerts tc.Alerts, inf *api.APIInfo, w http.ResponseWriter, r *http.Request) {
+func getSSLKeysByXMLIDHelper(xmlID string, tv trafficvault.TrafficVault, alerts tc.Alerts, inf *api.APIInfo, w http.ResponseWriter, r *http.Request) {
 	version := inf.Params["version"]
 	decode := inf.Params["decode"]
 	if userErr, sysErr, errCode := tenant.Check(inf.User, xmlID, inf.Tx.Tx); userErr != nil || sysErr != nil {
@@ -242,13 +242,14 @@ func getSSLKeysByXMLIDHelper(xmlID string, alerts tc.Alerts, inf *api.APIInfo, w
 		api.WriteAlerts(w, r, errCode, alerts)
 		return
 	}
-	keyObj, ok, err := riaksvc.GetDeliveryServiceSSLKeysObj(xmlID, version, inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	keyObjV15, ok, err := tv.GetDeliveryServiceSSLKeys(xmlID, version, inf.Tx.Tx)
 	if err != nil {
 		userErr := api.LogErr(r, http.StatusInternalServerError, nil, errors.New("getting ssl keys: "+err.Error()))
 		alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
 		api.WriteAlerts(w, r, http.StatusInternalServerError, alerts)
 		return
 	}
+	keyObj := keyObjV15.DeliveryServiceSSLKeys
 	if !ok {
 		keyObj = tc.DeliveryServiceSSLKeys{}
 	}
@@ -277,8 +278,8 @@ func GetSSLKeysByXMLIDV15(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 	defer inf.Close()
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Riak by xml id: Riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting SSL keys from Traffic Vault by xml id: Traffic Vault is not configured"))
 		return
 	}
 	xmlID := inf.Params["xmlid"]
@@ -294,7 +295,7 @@ func getSSLKeysByXMLIDHelperV15(xmlID string, alerts tc.Alerts, inf *api.APIInfo
 		api.WriteAlerts(w, r, errCode, alerts)
 		return
 	}
-	keyObj, ok, err := riaksvc.GetDeliveryServiceSSLKeysObjV15(xmlID, version, inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	keyObj, ok, err := inf.Vault.GetDeliveryServiceSSLKeys(xmlID, version, inf.Tx.Tx)
 	if err != nil {
 		userErr := api.LogErr(r, http.StatusInternalServerError, nil, errors.New("getting ssl keys: "+err.Error()))
 		alerts.AddNewAlert(tc.ErrorLevel, userErr.Error())
@@ -392,8 +393,8 @@ func deleteSSLKeys(w http.ResponseWriter, r *http.Request, deprecated bool) {
 		return
 	}
 	defer inf.Close()
-	if inf.Config.RiakEnabled == false {
-		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured"), deprecated, &alt)
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Traffic Vault is not configured"), deprecated, &alt)
 		return
 	}
 	xmlID := inf.Params["xmlid"]
@@ -409,7 +410,7 @@ func deleteSSLKeys(w http.ResponseWriter, r *http.Request, deprecated bool) {
 		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, errCode, userErr, sysErr, deprecated, &alt)
 		return
 	}
-	if err := riaksvc.DeleteDSSSLKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, xmlID, inf.Params["version"]); err != nil {
+	if err := inf.Vault.DeleteDeliveryServiceSSLKeys(xmlID, inf.Params["version"], inf.Tx.Tx); err != nil {
 		api.HandleErrOptionalDeprecation(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: deleting SSL keys: "+err.Error()), deprecated, &alt)
 		return
 	}
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/letsencryptcert.go b/traffic_ops/traffic_ops_golang/deliveryservice/letsencryptcert.go
index 37bb781..2066cfc 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/letsencryptcert.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/letsencryptcert.go
@@ -37,8 +37,8 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 
 	"github.com/go-acme/lego/certificate"
 	"github.com/go-acme/lego/challenge/dns01"
@@ -137,6 +137,11 @@ func GenerateLetsEncryptCertificates(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deliveryservice.GenerateLetsEncryptCertificates: Traffic Vault is not configured"))
+		return
+	}
+
 	ctx, _ := context.WithTimeout(r.Context(), LetsEncryptTimeout)
 
 	req := tc.DeliveryServiceLetsEncryptSSLKeysReq{}
@@ -177,13 +182,13 @@ func GenerateLetsEncryptCertificates(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	go GetLetsEncryptCertificates(inf.Config, req, ctx, inf.User)
+	go GetLetsEncryptCertificates(inf.Config, req, ctx, inf.User, inf.Vault)
 
 	api.WriteRespAlert(w, r, tc.SuccessLevel, "Beginning async call to Let's Encrypt for "+*req.DeliveryService+". This may take a few minutes.")
 
 }
 
-func GetLetsEncryptCertificates(cfg *config.Config, req tc.DeliveryServiceLetsEncryptSSLKeysReq, ctx context.Context, currentUser *auth.CurrentUser) error {
+func GetLetsEncryptCertificates(cfg *config.Config, req tc.DeliveryServiceLetsEncryptSSLKeysReq, ctx context.Context, currentUser *auth.CurrentUser, tv trafficvault.TrafficVault) error {
 
 	db, err := api.GetDB(ctx)
 	if err != nil {
@@ -293,10 +298,10 @@ func GetLetsEncryptCertificates(cfg *config.Config, req tc.DeliveryServiceLetsEn
 		CSR: string(EncodePEMToLegacyPerlRiakFormat([]byte("Lets Encrypt Generated"))),
 	}
 
-	if err := riaksvc.PutDeliveryServiceSSLKeysObj(dsSSLKeys, tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-		log.Errorf("Error posting lets encrypt certificate to riak: %s", err.Error())
+	if err := tv.PutDeliveryServiceSSLKeys(dsSSLKeys, tx); err != nil {
+		log.Errorf("Error putting lets encrypt certificate in Traffic Vault: %s", err.Error())
 		api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*req.DeliveryService+", ID: "+strconv.Itoa(dsID)+", ACTION: FAILED to add SSL keys with Lets Encrypt", currentUser, logTx)
-		return errors.New(deliveryService + ": putting riak keys: " + err.Error())
+		return errors.New(deliveryService + ": putting keys in Traffic Vault: " + err.Error())
 	}
 
 	tx2, err := db.Begin()
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go b/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
index 75e1494..14a0334 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/sslkeys.go
@@ -27,9 +27,8 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 )
 
 // GenerateSSLKeys generates a new private key, certificate signing request and
@@ -43,6 +42,11 @@ func GenerateSSLKeys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deliveryservice.GenerateSSLKeys: Traffic Vault is not configured"))
+		return
+	}
+
 	req := tc.DeliveryServiceGenSSLKeysReq{}
 	if err := api.Parse(r.Body, inf.Tx.Tx, &req); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("parsing request: "+err.Error()), nil)
@@ -60,7 +64,7 @@ func GenerateSSLKeys(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusNotFound, errors.New("no DS with name "+*req.DeliveryService), nil)
 		return
 	}
-	if err := generatePutRiakKeys(req, inf.Tx.Tx, inf.Config); err != nil {
+	if err := generatePutRiakKeys(req, inf.Tx.Tx, inf.Vault); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("generating and putting SSL keys: "+err.Error()))
 		return
 	}
@@ -74,7 +78,7 @@ func GenerateSSLKeys(w http.ResponseWriter, r *http.Request) {
 
 // generatePutRiakKeys generates a certificate, csr, and key from the given request, and insert it into the Riak key database.
 // The req MUST be validated, ensuring required fields exist.
-func generatePutRiakKeys(req tc.DeliveryServiceGenSSLKeysReq, tx *sql.Tx, cfg *config.Config) error {
+func generatePutRiakKeys(req tc.DeliveryServiceGenSSLKeysReq, tx *sql.Tx, tv trafficvault.TrafficVault) error {
 	dsSSLKeys := tc.DeliveryServiceSSLKeys{
 		CDN:             *req.CDN,
 		DeliveryService: *req.DeliveryService,
@@ -95,8 +99,8 @@ func generatePutRiakKeys(req tc.DeliveryServiceGenSSLKeysReq, tx *sql.Tx, cfg *c
 
 	dsSSLKeys.AuthType = tc.SelfSignedCertAuthType
 
-	if err := riaksvc.PutDeliveryServiceSSLKeysObj(dsSSLKeys, tx, cfg.RiakAuthOptions, cfg.RiakPort); err != nil {
-		return errors.New("putting riak keys: " + err.Error())
+	if err := tv.PutDeliveryServiceSSLKeys(dsSSLKeys, tx); err != nil {
+		return errors.New("putting keys in Traffic Vault: " + err.Error())
 	}
 	return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go b/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
index e4bdb6d..4d7f16a 100644
--- a/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
+++ b/traffic_ops/traffic_ops_golang/deliveryservice/urlkey.go
@@ -30,7 +30,6 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/dbhelpers"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
 )
 
@@ -42,8 +41,8 @@ func GetURLKeysByID(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured!"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.GetURLKeysByID: Traffic Vault is not configured"))
 		return
 	}
 
@@ -74,9 +73,9 @@ func GetURLKeysByID(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	keys, ok, err := riaksvc.GetURLSigKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, ds)
+	keys, ok, err := inf.Vault.GetURLSigKeys(string(ds), inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from riak: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from Traffic Vault: "+err.Error()))
 		return
 	}
 	if !ok {
@@ -94,8 +93,8 @@ func GetURLKeysByName(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured!"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.GetURLKeysByName: Traffic Vault is not configured"))
 		return
 	}
 
@@ -118,9 +117,9 @@ func GetURLKeysByName(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	keys, ok, err := riaksvc.GetURLSigKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, ds)
+	keys, ok, err := inf.Vault.GetURLSigKeys(string(ds), inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from riak: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from Traffic Vault: "+err.Error()))
 		return
 	}
 	if !ok {
@@ -138,8 +137,8 @@ func CopyURLKeys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured!"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.CopyURLKeys: Traffic Vault is not configured"))
 		return
 	}
 
@@ -191,9 +190,9 @@ func CopyURLKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	keys, ok, err := riaksvc.GetURLSigKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, copyDS)
+	keys, ok, err := inf.Vault.GetURLSigKeys(string(copyDS), inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from riak: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URL Sig keys from Traffic Vault: "+err.Error()))
 		return
 	}
 	if !ok {
@@ -201,7 +200,7 @@ func CopyURLKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if err := riaksvc.PutURLSigKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, ds, keys); err != nil {
+	if err := inf.Vault.PutURLSigKeys(string(ds), keys, inf.Tx.Tx); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("setting URL Sig keys for '"+string(ds)+" copied from "+string(copyDS)+": "+err.Error()))
 		return
 	}
@@ -217,8 +216,8 @@ func GenerateURLKeys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.DeleteSSLKeys: Riak is not configured!"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("deliveryservice.GenerateURLKeys: Traffic Vault is not configured"))
 		return
 	}
 
@@ -256,7 +255,7 @@ func GenerateURLKeys(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if err := riaksvc.PutURLSigKeys(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, ds, keys); err != nil {
+	if err := inf.Vault.PutURLSigKeys(string(ds), keys, inf.Tx.Tx); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("setting URL Sig keys for '"+string(ds)+": "+err.Error()))
 		return
 	}
diff --git a/traffic_ops/traffic_ops_golang/login/logout_test.go b/traffic_ops/traffic_ops_golang/login/logout_test.go
index da3bd4f..10bd9c8 100644
--- a/traffic_ops/traffic_ops_golang/login/logout_test.go
+++ b/traffic_ops/traffic_ops_golang/login/logout_test.go
@@ -19,19 +19,23 @@ package login
  * under the License.
  */
 
-import "context"
-import "net/http"
-import "net/http/httptest"
-import "testing"
-import "time"
-
-import "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-import "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
-import "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
-import "github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tocookie"
-
-import "github.com/jmoiron/sqlx"
-import sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
+import (
+	"context"
+	"net/http"
+	"net/http/httptest"
+	"testing"
+	"time"
+
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tocookie"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled"
+
+	"github.com/jmoiron/sqlx"
+	sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
+)
 
 var testUser = auth.CurrentUser{
 	UserName:     "admin",
@@ -90,6 +94,8 @@ func TestLogout(t *testing.T) {
 	ctx = context.WithValue(ctx, api.APIRespWrittenKey, false)
 	ctx = context.WithValue(ctx, auth.CurrentUserKey, testUser)
 	ctx = context.WithValue(ctx, api.PathParamsKey, map[string]string{})
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, api.TrafficVaultContextKey, tv)
 	ctx, _ = context.WithDeadline(ctx, time.Now().Add(24*time.Hour))
 	req = req.WithContext(ctx)
 
diff --git a/traffic_ops/traffic_ops_golang/ping/keys.go b/traffic_ops/traffic_ops_golang/ping/keys.go
index eabb512..2e3e2aa 100644
--- a/traffic_ops/traffic_ops_golang/ping/keys.go
+++ b/traffic_ops/traffic_ops_golang/ping/keys.go
@@ -24,7 +24,6 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 )
 
 const API_VAULT_PING = "/vault/ping"
@@ -37,7 +36,7 @@ func Keys(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	pingResp, err := riaksvc.Ping(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	pingResp, err := inf.Vault.Ping(inf.Tx.Tx)
 	if err != nil {
 		api.HandleDeprecatedErr(w, r, nil, http.StatusInternalServerError, err, nil, util.StrPtr(API_VAULT_PING))
 		return
diff --git a/traffic_ops/traffic_ops_golang/ping/riak.go b/traffic_ops/traffic_ops_golang/ping/riak.go
index 3e417d7..1d2b403 100644
--- a/traffic_ops/traffic_ops_golang/ping/riak.go
+++ b/traffic_ops/traffic_ops_golang/ping/riak.go
@@ -26,7 +26,6 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 )
 
 func Riak(w http.ResponseWriter, r *http.Request) {
@@ -42,7 +41,7 @@ func Riak(w http.ResponseWriter, r *http.Request) {
 
 	defer inf.Close()
 
-	pingResp, err := riaksvc.Ping(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	pingResp, err := inf.Vault.Ping(inf.Tx.Tx)
 
 	if err != nil {
 		userErr = api.LogErr(r, http.StatusInternalServerError, nil, errors.New("error pinging Riak: "+err.Error()))
diff --git a/traffic_ops/traffic_ops_golang/ping/vault.go b/traffic_ops/traffic_ops_golang/ping/vault.go
index 5916ece..f8f4bd5 100644
--- a/traffic_ops/traffic_ops_golang/ping/vault.go
+++ b/traffic_ops/traffic_ops_golang/ping/vault.go
@@ -24,7 +24,6 @@ import (
 	"net/http"
 
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 )
 
 func Vault(w http.ResponseWriter, r *http.Request) {
@@ -35,7 +34,7 @@ func Vault(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	pingResp, err := riaksvc.Ping(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	pingResp, err := inf.Vault.Ping(inf.Tx.Tx)
 	if err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("error pinging Riak: "+err.Error()))
 		return
diff --git a/traffic_ops/traffic_ops_golang/profile/copy_test.go b/traffic_ops/traffic_ops_golang/profile/copy_test.go
index 773a5ad..cdd6f92 100644
--- a/traffic_ops/traffic_ops_golang/profile/copy_test.go
+++ b/traffic_ops/traffic_ops_golang/profile/copy_test.go
@@ -33,9 +33,10 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/auth"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled"
 
 	"github.com/jmoiron/sqlx"
-
 	sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1"
 )
 
@@ -317,6 +318,8 @@ func mockHTTPReq(t *testing.T, path string, db *sqlx.DB) *http.Request {
 	ctx = context.WithValue(ctx, "db", db)
 	ctx = context.WithValue(ctx, "context", &cfg)
 	ctx = context.WithValue(ctx, "reqid", uint64(0))
+	var tv trafficvault.TrafficVault = &disabled.Disabled{}
+	ctx = context.WithValue(ctx, api.TrafficVaultContextKey, tv)
 	ctx = context.WithValue(ctx, "pathParams", map[string]string{"existing_profile": "existingProfile", "new_profile": "newProfile"})
 
 	// Add our context to the request
diff --git a/traffic_ops/traffic_ops_golang/routing/routing.go b/traffic_ops/traffic_ops_golang/routing/routing.go
index faa1833..9129f6d 100644
--- a/traffic_ops/traffic_ops_golang/routing/routing.go
+++ b/traffic_ops/traffic_ops_golang/routing/routing.go
@@ -38,6 +38,7 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/plugin"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/routing/middleware"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
 
 	"github.com/jmoiron/sqlx"
 )
@@ -76,9 +77,10 @@ type RawRoute struct {
 // ServerData ...
 type ServerData struct {
 	config.Config
-	DB        *sqlx.DB
-	Profiling *bool // Yes this is a field in the config but we want to live reload this value and NOT the entire config
-	Plugins   plugin.Plugins
+	DB           *sqlx.DB
+	Profiling    *bool // Yes this is a field in the config but we want to live reload this value and NOT the entire config
+	Plugins      plugin.Plugins
+	TrafficVault trafficvault.TrafficVault
 }
 
 // CompiledRoute ...
@@ -235,6 +237,7 @@ func Handler(
 	cfg *config.Config,
 	getReqID func() uint64,
 	plugins plugin.Plugins,
+	tv trafficvault.TrafficVault,
 	w http.ResponseWriter,
 	r *http.Request,
 ) {
@@ -251,6 +254,7 @@ func Handler(
 	ctx = context.WithValue(ctx, api.DBContextKey, db)
 	ctx = context.WithValue(ctx, api.ConfigContextKey, cfg)
 	ctx = context.WithValue(ctx, api.ReqIDContextKey, reqID)
+	ctx = context.WithValue(ctx, api.TrafficVaultContextKey, tv)
 
 	// plugins have no pre-parsed path params, but add an empty map so they can use the api helper funcs that require it.
 	pluginCtx := context.WithValue(ctx, api.PathParamsKey, map[string]string{})
@@ -344,7 +348,7 @@ func RegisterRoutes(d ServerData) error {
 	compiledRoutes := CompileRoutes(routes)
 	getReqID := nextReqIDGetter()
 	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-		Handler(compiledRoutes, versions, catchall, d.DB, &d.Config, getReqID, d.Plugins, w, r)
+		Handler(compiledRoutes, versions, catchall, d.DB, &d.Config, getReqID, d.Plugins, d.TrafficVault, w, r)
 	})
 	return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
index ed1d55f..f1701e9 100644
--- a/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
+++ b/traffic_ops/traffic_ops_golang/traffic_ops_golang.go
@@ -21,15 +21,16 @@ package main
 
 import (
 	"crypto/tls"
+	"encoding/json"
 	"flag"
 	"fmt"
+	"io/ioutil"
 	"net/http"
 	_ "net/http/pprof"
 	"os"
 	"os/signal"
 	"path/filepath"
 	"runtime/pprof"
-	"strconv"
 	"strings"
 	"time"
 
@@ -39,6 +40,9 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/config"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/plugin"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/routing"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc"
 
 	"github.com/jmoiron/sqlx"
 	_ "github.com/lib/pq"
@@ -58,7 +62,7 @@ func main() {
 	showRoutes := flag.Bool("api-routes", false, "Show the list of API routes and exit")
 	configFileName := flag.String("cfg", "", "The config file path")
 	dbConfigFileName := flag.String("dbcfg", "", "The db config file path")
-	riakConfigFileName := flag.String("riakcfg", "", "The riak config file path")
+	riakConfigFileName := flag.String("riakcfg", "", "The riak config file path (DEPRECATED: use traffic_vault_backend = riak and traffic_vault_config in cdn.conf instead)")
 	flag.Parse()
 
 	if *showVersion {
@@ -95,7 +99,7 @@ func main() {
 		os.Exit(1)
 	}
 
-	cfg, errsToLog, blockStart := config.LoadConfig(*configFileName, *dbConfigFileName, *riakConfigFileName, version)
+	cfg, errsToLog, blockStart := config.LoadConfig(*configFileName, *dbConfigFileName, version)
 	for _, err := range errsToLog {
 		fmt.Fprintf(os.Stderr, "Loading Config: %v\n", err)
 	}
@@ -138,6 +142,8 @@ func main() {
 	db.SetMaxIdleConns(cfg.DBMaxIdleConnections)
 	db.SetConnMaxLifetime(time.Duration(cfg.DBConnMaxLifetimeSeconds) * time.Second)
 
+	trafficVault := setupTrafficVault(*riakConfigFileName, &cfg)
+
 	// TODO combine
 	plugins := plugin.Get(cfg)
 	profiling := cfg.ProfilingEnabled
@@ -155,7 +161,7 @@ func main() {
 		log.Errorln(debugServer.ListenAndServe())
 	}()
 
-	if err := routing.RegisterRoutes(routing.ServerData{DB: db, Config: cfg, Profiling: &profiling, Plugins: plugins}); err != nil {
+	if err := routing.RegisterRoutes(routing.ServerData{DB: db, Config: cfg, Profiling: &profiling, Plugins: plugins, TrafficVault: trafficVault}); err != nil {
 		log.Errorf("registering routes: %v\n", err)
 		os.Exit(1)
 	}
@@ -229,6 +235,61 @@ func main() {
 	signalReloader(unix.SIGHUP, reloadProfilingConfig)
 }
 
+func setupTrafficVault(riakConfigFileName string, cfg *config.Config) trafficvault.TrafficVault {
+	var err error
+	trafficVaultConfigBytes := []byte{}
+	trafficVaultBackend := ""
+	if len(riakConfigFileName) > 0 {
+		// use legacy riak config if given
+		log.Warnln("using deprecated --riakcfg flag, use traffic_vault_backend = riak and traffic_vault_config in cdn.conf instead")
+		trafficVaultConfigBytes, err = ioutil.ReadFile(riakConfigFileName)
+		if err != nil {
+			log.Errorf("reading riak conf '%s': %s", riakConfigFileName, err.Error())
+			os.Exit(1)
+		}
+		cfg.TrafficVaultEnabled = true
+		trafficVaultBackend = riaksvc.RiakBackendName
+	}
+	if len(cfg.TrafficVaultBackend) > 0 {
+		if len(cfg.TrafficVaultConfig) == 0 {
+			log.Errorln("traffic_vault_backend is non-empty but traffic_vault_config is empty")
+			os.Exit(1)
+		}
+		cfg.TrafficVaultEnabled = true
+		// traffic_vault_config should override legacy riak config if both are used
+		trafficVaultConfigBytes = cfg.TrafficVaultConfig
+		trafficVaultBackend = cfg.TrafficVaultBackend
+	}
+	if trafficVaultBackend == riaksvc.RiakBackendName && cfg.RiakPort != nil {
+		// inject riak_port into traffic_vault_config.port if unset there
+		log.Warnln("using deprecated field 'riak_port', use 'port' field in traffic_vault_config instead")
+		tmp := make(map[string]interface{})
+		err := json.Unmarshal(trafficVaultConfigBytes, &tmp)
+		if err != nil {
+			log.Errorf("failed to unmarshal riak config: %s", err.Error())
+			os.Exit(1)
+		}
+		if _, ok := tmp["port"]; !ok {
+			tmp["port"] = *cfg.RiakPort
+		}
+		trafficVaultConfigBytes, err = json.Marshal(tmp)
+		if err != nil {
+			log.Errorf("failed to marshal riak config: %s", err.Error())
+			os.Exit(1)
+		}
+	}
+
+	if cfg.TrafficVaultEnabled {
+		trafficVault, err := trafficvault.GetBackend(trafficVaultBackend, trafficVaultConfigBytes)
+		if err != nil {
+			log.Errorf("failed to get Traffic Vault backend '%s': %s", cfg.TrafficVaultBackend, err.Error())
+			os.Exit(1)
+		}
+		return trafficVault
+	}
+	return &disabled.Disabled{}
+}
+
 func setNewProfilingInfo(configFileName string, currentProfilingEnabled *bool, currentProfilingLocation *string, version string) {
 	newProfilingEnabled, newProfilingLocation, err := reloadProfilingInfo(configFileName)
 	if err != nil {
@@ -321,10 +382,6 @@ func signalReloader(sig os.Signal, f func()) {
 }
 
 func logConfig(cfg config.Config) {
-	logRiakPort := "<nil>"
-	if cfg.RiakPort != nil {
-		logRiakPort = strconv.Itoa(int(*cfg.RiakPort))
-	}
 	log.Infof(`Using Config values:
 		Port:                 %s
 		Db Server:            %s
@@ -349,7 +406,6 @@ func logConfig(cfg config.Config) {
 		Info Log:             %s
 		Debug Log:            %s
 		Event Log:            %s
-		Riak Port:            %v
 		LDAP Enabled:         %v
-		InfluxDB Enabled:     %v`, cfg.Port, cfg.DB.Hostname, cfg.DB.User, cfg.DB.DBName, cfg.DB.SSL, cfg.MaxDBConnections, cfg.Listen[0], cfg.Insecure, cfg.CertPath, cfg.KeyPath, time.Duration(cfg.ProxyTimeout)*time.Second, time.Duration(cfg.ProxyKeepAlive)*time.Second, time.Duration(cfg.ProxyTLSTimeout)*time.Second, time.Duration(cfg.ProxyReadHeaderTimeout)*time.Second, time.Duration(cfg.ReadTimeout)*time.Second, time.Duration(cfg.ReadHeaderTimeout)*time.Second, time.Duration(cfg.WriteTimeou [...]
+		InfluxDB Enabled:     %v`, cfg.Port, cfg.DB.Hostname, cfg.DB.User, cfg.DB.DBName, cfg.DB.SSL, cfg.MaxDBConnections, cfg.Listen[0], cfg.Insecure, cfg.CertPath, cfg.KeyPath, time.Duration(cfg.ProxyTimeout)*time.Second, time.Duration(cfg.ProxyKeepAlive)*time.Second, time.Duration(cfg.ProxyTLSTimeout)*time.Second, time.Duration(cfg.ProxyReadHeaderTimeout)*time.Second, time.Duration(cfg.ReadTimeout)*time.Second, time.Duration(cfg.ReadHeaderTimeout)*time.Second, time.Duration(cfg.WriteTimeou [...]
 }
diff --git a/traffic_ops/traffic_ops_golang/trafficvault/README.md b/traffic_ops/traffic_ops_golang/trafficvault/README.md
new file mode 100644
index 0000000..cbff240
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficvault/README.md
@@ -0,0 +1,61 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+
+# Implementing a new Traffic Vault backend (e.g. Foo)
+
+1. Create a new directory in ./backends which will contain/define your new package (`foo`) which will provide all the functionality to support a new `Foo` backend for Traffic Vault.
+2. In this new `./backends/foo` directory, create a new file: `foo.go`, with `package foo` to define the package name.
+3. In `foo.go`, define a struct (e.g. `type Foo struct`) which will act as the method receiver for all the required `TrafficVault` methods. This struct should contain any fields necessary to provide the required functionality. For instance, it should most likely contain all the required configuration to connect to and use the `Foo` data store.
+```go
+type Foo struct {
+    cfg Config
+}
+
+type Config struct {
+    user     string
+    password string
+}
+```
+4. Implement all the methods required by the `TrafficVault` interface on your new `Foo` struct. Initially, you may want to simply stub out the methods and implement them later:
+```go
+func (f *Foo) GetDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) (tc.DeliveryServiceSSLKeysV15, bool, error) {
+	return tc.DeliveryServiceSSLKeysV15{}, false, nil
+}
+
+... (snip)
+
+func (f *Foo) Ping(tx *sql.Tx) (tc.TrafficVaultPingResponse, error) {
+	return tc.TrafficVaultPingResponse{}, nil
+}
+```
+5. Define a `trafficvault.LoadFunc` which will parse the given JSON config (from cdn.conf's `traffic_vault_config` option) and return a pointer to an instance of the `Foo` type:
+```go
+func loadFoo(b json.RawMessage) (trafficvault.TrafficVault, error) {
+    // unmarshal the given JSON, validate it, return an error if any
+    // fooCfg, err := parseAndValidateConfig(b)
+	return &Foo{cfg: fooCfg}, nil
+}
+```
+6. Define a package `init` function which calls `trafficvault.AddBackend` with your backend's name and `LoadFunc` in order to register your new Traffic Vault `Foo` backend for use:
+```go
+func init() {
+	trafficvault.AddBackend("foo", loadFoo)
+}
+```
+7. You are now able to test your new Traffic Vault `Foo` backend. First, in `cdn.conf`, you need to set `traffic_vault_backend` to `"foo"` and include your desired `Foo` configuration in `traffic_vault_config`. Once that is done, Traffic Vault is enabled, and you can use Traffic Ops API routes that require Traffic Vault. At this point, you should go back and fully implement the stubbed out `TrafficVault` interface methods on your `Foo` type.
diff --git a/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled/disabled.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled/disabled.go
new file mode 100644
index 0000000..4e615dc
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/disabled/disabled.go
@@ -0,0 +1,100 @@
+// Package disabled provides a TrafficVault implementation that simply returns an
+// error for every method stating that Traffic Vault is disabled. This is used instead
+// of passing around a nil TrafficVault instance when Traffic Vault is not enabled, in
+// order to reduce the likelihood of accidentally de-referencing a nil pointer.
+package disabled
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+	"database/sql"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+type Error string
+
+func (e Error) Error() string {
+	return string(e)
+}
+
+const disabledErr = Error("traffic vault is disabled")
+
+type Disabled struct {
+}
+
+func (d *Disabled) GetDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) (tc.DeliveryServiceSSLKeysV15, bool, error) {
+	return tc.DeliveryServiceSSLKeysV15{}, false, disabledErr
+}
+
+func (d *Disabled) PutDeliveryServiceSSLKeys(key tc.DeliveryServiceSSLKeys, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) DeleteDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) DeleteOldDeliveryServiceSSLKeys(existingXMLIDs map[string]struct{}, cdnName string, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) GetCDNSSLKeys(cdnName string, tx *sql.Tx) ([]tc.CDNSSLKey, error) {
+	return nil, disabledErr
+}
+
+func (d *Disabled) GetDNSSECKeys(cdnName string, tx *sql.Tx) (tc.DNSSECKeysTrafficVault, bool, error) {
+	return nil, false, disabledErr
+}
+
+func (d *Disabled) PutDNSSECKeys(cdnName string, keys tc.DNSSECKeysTrafficVault, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) DeleteDNSSECKeys(cdnName string, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) GetURLSigKeys(xmlID string, tx *sql.Tx) (tc.URLSigKeys, bool, error) {
+	return nil, false, disabledErr
+}
+
+func (d *Disabled) PutURLSigKeys(xmlID string, keys tc.URLSigKeys, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) GetURISigningKeys(xmlID string, tx *sql.Tx) ([]byte, bool, error) {
+	return nil, false, disabledErr
+}
+
+func (d *Disabled) PutURISigningKeys(xmlID string, keysJson []byte, tx *sql.Tx) error {
+	return disabledErr
+}
+
+func (d *Disabled) DeleteURISigningKeys(xmlID string, tx *sql.Tx) error {
+	return disabledErr
+}
+func (d *Disabled) Ping(tx *sql.Tx) (tc.TrafficVaultPingResponse, error) {
+	return tc.TrafficVaultPingResponse{}, disabledErr
+}
+
+func (d *Disabled) GetBucketKey(bucket string, key string, tx *sql.Tx) ([]byte, bool, error) {
+	return nil, false, disabledErr
+}
diff --git a/traffic_ops/traffic_ops_golang/riaksvc/dsutil.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/dsutil.go
similarity index 54%
rename from traffic_ops/traffic_ops_golang/riaksvc/dsutil.go
rename to traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/dsutil.go
index 46ab0eb..5c951ac 100644
--- a/traffic_ops/traffic_ops_golang/riaksvc/dsutil.go
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/dsutil.go
@@ -23,6 +23,7 @@ import (
 	"database/sql"
 	"encoding/json"
 	"errors"
+	"strings"
 
 	"github.com/apache/trafficcontrol/lib/go-log"
 	"github.com/apache/trafficcontrol/lib/go-tc"
@@ -30,51 +31,28 @@ import (
 	"github.com/basho/riak-go-client"
 )
 
-const DeliveryServiceSSLKeysBucket = "ssl"
-const DNSSECKeysBucket = "dnssec"
-const DSSSLKeyVersionLatest = "latest"
-const DefaultDSSSLKeyVersion = DSSSLKeyVersionLatest
-const URLSigKeysBucket = "url_sig_keys"
-const URISigningKeysBucket = "cdn_uri_sig_keys"
+const deliveryServiceSSLKeysBucket = "ssl"
+const dnssecKeysBucket = "dnssec"
+const dsSSLKeyVersionLatest = "latest"
+const defaultDSSSLKeyVersion = dsSSLKeyVersionLatest
+const urlSigKeysBucket = "url_sig_keys"
 
-func MakeDSSSLKeyKey(dsName, version string) string {
+// cdnURIKeysBucket is the namespace or bucket used for CDN URI signing keys.
+const cdnURIKeysBucket = "cdn_uri_sig_keys"
+
+func makeDSSSLKeyKey(dsName, version string) string {
 	if version == "" {
-		version = DefaultDSSSLKeyVersion
+		version = defaultDSSSLKeyVersion
 	}
 	return dsName + "-" + version
 }
 
-func GetDeliveryServiceSSLKeysObj(xmlID string, version string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.DeliveryServiceSSLKeys, bool, error) {
-	key := tc.DeliveryServiceSSLKeys{}
-	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		// get the deliveryservice ssl keys by xmlID and version
-		ro, err := FetchObjectValues(MakeDSSSLKeyKey(xmlID, version), DeliveryServiceSSLKeysBucket, cluster)
-		if err != nil {
-			return err
-		}
-		if len(ro) == 0 {
-			return nil // not found
-		}
-		if err := json.Unmarshal(ro[0].Value, &key); err != nil {
-			log.Errorf("failed at unmarshaling sslkey response: %s\n", err)
-			return errors.New("unmarshalling Riak result: " + err.Error())
-		}
-		found = true
-		return nil
-	})
-	if err != nil {
-		return key, false, err
-	}
-	return key, found, nil
-}
-
-func GetDeliveryServiceSSLKeysObjV15(xmlID string, version string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.DeliveryServiceSSLKeysV15, bool, error) {
+func getDeliveryServiceSSLKeysObjV15(xmlID string, version string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.DeliveryServiceSSLKeysV15, bool, error) {
 	key := tc.DeliveryServiceSSLKeysV15{}
 	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		// get the deliveryservice ssl keys by xmlID and version
-		ro, err := FetchObjectValues(MakeDSSSLKeyKey(xmlID, version), DeliveryServiceSSLKeysBucket, cluster)
+		ro, err := fetchObjectValues(makeDSSSLKeyKey(xmlID, version), deliveryServiceSSLKeysBucket, cluster)
 		if err != nil {
 			return err
 		}
@@ -94,24 +72,24 @@ func GetDeliveryServiceSSLKeysObjV15(xmlID string, version string, tx *sql.Tx, a
 	return key, found, nil
 }
 
-func PutDeliveryServiceSSLKeysObj(key tc.DeliveryServiceSSLKeys, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) error {
+func putDeliveryServiceSSLKeysObj(key tc.DeliveryServiceSSLKeys, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) error {
 	keyJSON, err := json.Marshal(&key)
 	if err != nil {
 		return errors.New("marshalling key: " + err.Error())
 	}
-	err = WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err = withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		obj := &riak.Object{
 			ContentType:     "application/json",
 			Charset:         "utf-8",
 			ContentEncoding: "utf-8",
-			Key:             MakeDSSSLKeyKey(key.DeliveryService, key.Version.String()),
+			Key:             makeDSSSLKeyKey(key.DeliveryService, key.Version.String()),
 			Value:           []byte(keyJSON),
 		}
-		if err := SaveObject(obj, DeliveryServiceSSLKeysBucket, cluster); err != nil {
+		if err := saveObject(obj, deliveryServiceSSLKeysBucket, cluster); err != nil {
 			return errors.New("saving Riak object: " + err.Error())
 		}
-		obj.Key = MakeDSSSLKeyKey(key.DeliveryService, DSSSLKeyVersionLatest)
-		if err := SaveObject(obj, DeliveryServiceSSLKeysBucket, cluster); err != nil {
+		obj.Key = makeDSSSLKeyKey(key.DeliveryService, dsSSLKeyVersionLatest)
+		if err := saveObject(obj, deliveryServiceSSLKeysBucket, cluster); err != nil {
 			return errors.New("saving Riak object: " + err.Error())
 		}
 		return nil
@@ -119,13 +97,13 @@ func PutDeliveryServiceSSLKeysObj(key tc.DeliveryServiceSSLKeys, tx *sql.Tx, aut
 	return err
 }
 
-func Ping(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.RiakPingResp, error) {
-	servers, err := GetRiakServers(tx, riakPort)
+func ping(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.RiakPingResp, error) {
+	servers, err := getRiakServers(tx, riakPort)
 	if err != nil {
 		return tc.RiakPingResp{}, errors.New("getting riak servers: " + err.Error())
 	}
 	for _, server := range servers {
-		cluster, err := GetRiakStorageCluster([]ServerAddr{server}, authOpts)
+		cluster, err := getRiakStorageCluster([]ServerAddr{server}, authOpts)
 		if err != nil {
 			log.Errorf("RiakServersToCluster error for server %+v: %+v\n", server, err.Error())
 			continue // try another server
@@ -134,11 +112,11 @@ func Ping(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.RiakPingRe
 			log.Errorln("starting Riak cluster (for ping): " + err.Error())
 			continue
 		}
-		if err := PingCluster(cluster); err != nil {
+		if err := pingCluster(cluster); err != nil {
 			if err := cluster.Stop(); err != nil {
 				log.Errorln("stopping Riak cluster (after ping error): " + err.Error())
 			}
-			log.Errorf("Riak PingCluster error for server %+v: %+v\n", server, err.Error())
+			log.Errorf("Riak pingCluster error for server %+v: %+v\n", server, err.Error())
 			continue
 		}
 		if err := cluster.Stop(); err != nil {
@@ -149,11 +127,11 @@ func Ping(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.RiakPingRe
 	return tc.RiakPingResp{}, errors.New("failed to ping any Riak server")
 }
 
-func GetDNSSECKeys(cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.DNSSECKeysRiak, bool, error) {
+func getDNSSECKeys(cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) (tc.DNSSECKeysRiak, bool, error) {
 	key := tc.DNSSECKeysRiak{}
 	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		ro, err := FetchObjectValues(cdnName, DNSSECKeysBucket, cluster)
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+		ro, err := fetchObjectValues(cdnName, dnssecKeysBucket, cluster)
 		if err != nil {
 			return err
 		}
@@ -172,13 +150,13 @@ func GetDNSSECKeys(cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakP
 	return key, found, nil
 }
 
-func PutDNSSECKeys(keys tc.DNSSECKeysRiak, cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) error {
+func putDNSSECKeys(keys tc.DNSSECKeysRiak, cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) error {
 	keyJSON, err := json.Marshal(&keys)
 	if err != nil {
 		return errors.New("marshalling keys: " + err.Error())
 	}
 
-	err = WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err = withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		obj := &riak.Object{
 			ContentType:     "application/json",
 			Charset:         "utf-8",
@@ -186,7 +164,7 @@ func PutDNSSECKeys(keys tc.DNSSECKeysRiak, cdnName string, tx *sql.Tx, authOpts
 			Key:             cdnName,
 			Value:           []byte(keyJSON),
 		}
-		if err = SaveObject(obj, DNSSECKeysBucket, cluster); err != nil {
+		if err = saveObject(obj, dnssecKeysBucket, cluster); err != nil {
 			return errors.New("saving Riak object: " + err.Error())
 		}
 		return nil
@@ -194,12 +172,23 @@ func PutDNSSECKeys(keys tc.DNSSECKeysRiak, cdnName string, tx *sql.Tx, authOpts
 	return err
 }
 
-func GetBucketKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, bucket string, key string) ([]byte, bool, error) {
+func deleteDNSSECKeys(cdnName string, tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint) error {
+	cluster, err := getPooledCluster(tx, authOpts, riakPort)
+	if err != nil {
+		return errors.New("getting riak cluster: " + err.Error())
+	}
+	if err := deleteObject(cdnName, dnssecKeysBucket, cluster); err != nil {
+		return errors.New("deleting riak object: " + err.Error())
+	}
+	return nil
+}
+
+func getBucketKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, bucket string, key string) ([]byte, bool, error) {
 	val := []byte{}
 	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		// get the deliveryservice ssl keys by xmlID and version
-		ro, err := FetchObjectValues(key, bucket, cluster)
+		ro, err := fetchObjectValues(key, bucket, cluster)
 		if err != nil {
 			return err
 		}
@@ -216,9 +205,9 @@ func GetBucketKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, bucket
 	return val, found, nil
 }
 
-func DeleteDSSSLKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xmlID string, version string) error {
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		if err := DeleteObject(MakeDSSSLKeyKey(xmlID, version), DeliveryServiceSSLKeysBucket, cluster); err != nil {
+func deleteDSSSLKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xmlID string, version string) error {
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+		if err := deleteObject(makeDSSSLKeyKey(xmlID, version), deliveryServiceSSLKeysBucket, cluster); err != nil {
 			return errors.New("deleting SSL keys: " + err.Error())
 		}
 		return nil
@@ -226,12 +215,12 @@ func DeleteDSSSLKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xml
 	return err
 }
 
-// DeleteDeliveryServicesSSLKey deletes a Delivery Service SSL key.
-// This should almost never be used directly, prefer DeleteDSSSLKeys instead.
-// This should only be used to delete keys, which may not conform to the MakeDSSSLKeyKey format. For example when deleting all keys on a delivery service, and some may have been created manually outside Traffic Ops, or are otherwise malformed.
-func DeleteDeliveryServicesSSLKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, key string) error {
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		if err := DeleteObject(key, DeliveryServiceSSLKeysBucket, cluster); err != nil {
+// deleteDeliveryServicesSSLKey deletes a Delivery Service SSL key.
+// This should almost never be used directly, prefer deleteDSSSLKeys instead.
+// This should only be used to delete keys, which may not conform to the makeDSSSLKeyKey format. For example when deleting all keys on a delivery service, and some may have been created manually outside Traffic Ops, or are otherwise malformed.
+func deleteDeliveryServicesSSLKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, key string) error {
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+		if err := deleteObject(key, deliveryServiceSSLKeysBucket, cluster); err != nil {
 			return errors.New("deleting SSL keys: " + err.Error())
 		}
 		return nil
@@ -239,18 +228,69 @@ func DeleteDeliveryServicesSSLKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPo
 	return err
 }
 
-// GetURLSigConfigFileName returns the filename of the Apache Traffic Server URLSig config file
+func getURISigningKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xmlID string) ([]byte, bool, error) {
+	cluster, err := getPooledCluster(tx, authOpts, riakPort)
+	if err != nil {
+		return nil, false, errors.New("getting pooled Riak cluster: " + err.Error())
+	}
+	ro, err := fetchObjectValues(xmlID, cdnURIKeysBucket, cluster)
+	if err != nil {
+		return nil, false, errors.New("fetching riak objects: " + err.Error())
+	}
+	if len(ro) == 0 {
+		bts, err := json.Marshal(tc.URISignerKeyset{})
+		if err != nil {
+			return nil, false, errors.New("marshalling empty URISignerKeyset: " + err.Error())
+		}
+		return bts, false, nil
+	}
+	if ro[0].Value == nil {
+		return ro[0].Value, false, nil
+	}
+	return ro[0].Value, true, nil
+}
+
+func deleteURISigningKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xmlID string) error {
+	cluster, err := getPooledCluster(tx, authOpts, riakPort)
+	if err != nil {
+		return errors.New("getting pooled Riak cluster: " + err.Error())
+	}
+	if err := deleteObject(xmlID, cdnURIKeysBucket, cluster); err != nil {
+		return errors.New("deleting object: " + err.Error())
+	}
+	return nil
+}
+
+func putURISigningKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, xmlID string, keysJson []byte) error {
+	cluster, err := getPooledCluster(tx, authOpts, riakPort)
+	if err != nil {
+		return errors.New("getting pooled Riak cluster: " + err.Error())
+	}
+	obj := &riak.Object{
+		ContentType:     "text/json",
+		Charset:         "utf-8",
+		ContentEncoding: "utf-8",
+		Key:             xmlID,
+		Value:           keysJson,
+	}
+	if err = saveObject(obj, cdnURIKeysBucket, cluster); err != nil {
+		return errors.New("saving riak object: " + err.Error())
+	}
+	return nil
+}
+
+// getURLSigConfigFileName returns the filename of the Apache Traffic Server URLSig config file
 // TODO move to ats config directory/file
-func GetURLSigConfigFileName(ds tc.DeliveryServiceName) string {
+func getURLSigConfigFileName(ds tc.DeliveryServiceName) string {
 	return "url_sig_" + string(ds) + ".config"
 }
 
-func GetURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc.DeliveryServiceName) (tc.URLSigKeys, bool, error) {
+func getURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc.DeliveryServiceName) (tc.URLSigKeys, bool, error) {
 	val := tc.URLSigKeys{}
 	found := false
-	key := GetURLSigConfigFileName(ds)
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		ro, err := FetchObjectValues(key, URLSigKeysBucket, cluster)
+	key := getURLSigConfigFileName(ds)
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+		ro, err := fetchObjectValues(key, urlSigKeysBucket, cluster)
 		if err != nil {
 			return err
 		}
@@ -269,20 +309,20 @@ func GetURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc
 	return val, found, nil
 }
 
-func PutURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc.DeliveryServiceName, keys tc.URLSigKeys) error {
+func putURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc.DeliveryServiceName, keys tc.URLSigKeys) error {
 	keyJSON, err := json.Marshal(&keys)
 	if err != nil {
 		return errors.New("marshalling keys: " + err.Error())
 	}
-	err = WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err = withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		obj := &riak.Object{
 			ContentType:     "application/json",
 			Charset:         "utf-8",
 			ContentEncoding: "utf-8",
-			Key:             GetURLSigConfigFileName(ds),
+			Key:             getURLSigConfigFileName(ds),
 			Value:           []byte(keyJSON),
 		}
-		if err = SaveObject(obj, URLSigKeysBucket, cluster); err != nil {
+		if err = saveObject(obj, urlSigKeysBucket, cluster); err != nil {
 			return errors.New("saving Riak object: " + err.Error())
 		}
 		return nil
@@ -290,24 +330,24 @@ func PutURLSigKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, ds tc
 	return err
 }
 
-const SSLKeysIndex = "sslkeys"
-const CDNSSLKeysLimit = 1000 // TODO: emulates Perl; reevaluate?
+const sslKeysIndex = "sslkeys"
+const cdnSSLKeysLimit = 1000 // TODO: emulates Perl; reevaluate?
 
-func GetCDNSSLKeysObj(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdnName string) ([]tc.CDNSSLKey, error) {
+func getCDNSSLKeysObj(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdnName string) ([]tc.CDNSSLKey, error) {
 	keys := []tc.CDNSSLKey{}
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		// get the deliveryservice ssl keys by xmlID and version
 		query := `cdn:` + cdnName
 		filterQuery := `_yz_rk:*latest`
 		fields := []string{"deliveryservice", "hostname", "certificate.crt", "certificate.key"}
-		searchDocs, err := Search(cluster, SSLKeysIndex, query, filterQuery, CDNSSLKeysLimit, fields)
+		searchDocs, err := search(cluster, sslKeysIndex, query, filterQuery, cdnSSLKeysLimit, fields)
 		if err != nil {
 			return errors.New("riak search error: " + err.Error())
 		}
 		if len(searchDocs) == 0 {
 			return nil // no error, and leave keys empty
 		}
-		keys = SearchDocsToCDNSSLKeys(searchDocs)
+		keys = searchDocsToCDNSSLKeys(searchDocs)
 		return nil
 	})
 	if err != nil {
@@ -316,8 +356,8 @@ func GetCDNSSLKeysObj(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cd
 	return keys, nil
 }
 
-// SearchDocsToCDNSSLKeys converts the SearchDoc array returned by Riak into a CDNSSLKey slice. If a SearchDoc doesn't contain expected fields, it creates the key with those fields defaulted to empty strings.
-func SearchDocsToCDNSSLKeys(docs []*riak.SearchDoc) []tc.CDNSSLKey {
+// searchDocsToCDNSSLKeys converts the SearchDoc array returned by Riak into a CDNSSLKey slice. If a SearchDoc doesn't contain expected fields, it creates the key with those fields defaulted to empty strings.
+func searchDocsToCDNSSLKeys(docs []*riak.SearchDoc) []tc.CDNSSLKey {
 	keys := []tc.CDNSSLKey{}
 	for _, doc := range docs {
 		key := tc.CDNSSLKey{}
@@ -338,16 +378,15 @@ func SearchDocsToCDNSSLKeys(docs []*riak.SearchDoc) []tc.CDNSSLKey {
 	return keys
 }
 
-// GetCDNSSLKeysDSNames returns the delivery service names (xml_id) of every delivery service on the given cdn with SSL keys in Riak, and the keys currently in Riak.
-// Returns map[tc.DeliveryServiceName][]key
-func GetCDNSSLKeysDSNames(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName) (map[tc.DeliveryServiceName][]string, error) {
-	dsVersions := map[tc.DeliveryServiceName][]string{}
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
+// deleteOldDeliveryServiceSSLKeys deletes all the SSL keys in Riak for delivery services in the given CDN that are not in the given existingXMLIDs.
+func deleteOldDeliveryServiceSSLKeys(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, cdn tc.CDNName, existingXMLIDs map[string]struct{}) error {
+	dsVersions := map[string][]string{}
+	err := withCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
 		// get the deliveryservice ssl keys by xmlID and version
 		query := `cdn:` + string(cdn)
 		filterQuery := ""
 		fields := []string{"_yz_rk", "deliveryservice"} // '_yz_rk' is the magic Riak field that populates the key. Without this, doc.Key would be empty.
-		searchDocs, err := Search(cluster, SSLKeysIndex, query, filterQuery, CDNSSLKeysLimit, fields)
+		searchDocs, err := search(cluster, sslKeysIndex, query, filterQuery, cdnSSLKeysLimit, fields)
 		if err != nil {
 			return errors.New("riak search error: " + err.Error())
 		}
@@ -364,60 +403,35 @@ func GetCDNSSLKeysDSNames(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint
 			if len(dses) > 1 {
 				log.Errorf("Riak had a CDN '"+string(cdn)+"' key with multiple delivery services '"+doc.Key+"' deliveryservices '%+v' - ignoring all but the first!\n", dses)
 			}
-			ds := tc.DeliveryServiceName(dses[0])
+			ds := dses[0]
 
 			dsVersions[ds] = append(dsVersions[ds], doc.Key)
 		}
 		return nil
 	})
 	if err != nil {
-		return nil, errors.New("with cluster error: " + err.Error())
+		return errors.New("with cluster error: " + err.Error())
 	}
-	return dsVersions, nil
-}
 
-// GetURISigningKeysRaw gets the URL Sig keys for the given delivery service, as the raw bytes stored in Riak.
-func GetURISigningKeysRaw(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, key string) ([]byte, bool, error) {
-	val := []byte(nil)
-	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		ro, err := FetchObjectValues(key, URISigningKeysBucket, cluster)
-		if err != nil {
-			return err
+	successes := []string{}
+	failures := []string{}
+	for ds, riakKeys := range dsVersions {
+		if _, ok := existingXMLIDs[ds]; ok {
+			continue
 		}
-		if len(ro) == 0 {
-			return nil // not found
+		for _, riakKey := range riakKeys {
+			err := deleteDeliveryServicesSSLKey(tx, authOpts, riakPort, riakKey)
+			if err != nil {
+				log.Errorln("deleting Traffic Vault SSL keys for Delivery Service '" + ds + "' key '" + riakKey + "': " + err.Error())
+				failures = append(failures, ds)
+			} else {
+				log.Infoln("Deleted Traffic Vault SSL keys for delivery service which has been deleted in the database '" + string(ds) + "' key '" + riakKey + "'")
+				successes = append(successes, ds)
+			}
 		}
-		val = ro[0].Value
-		found = true
-		return nil
-	})
-	if err != nil {
-		return nil, false, err
 	}
-	return val, found, nil
-}
-
-// GetURLSigKeysFromKey gets the URL Sig keys from the raw Riak key, which is the ATS config file name.
-func GetURLSigKeysFromConfigFileKey(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, configFileKey string) (tc.URLSigKeys, bool, error) {
-	val := tc.URLSigKeys{}
-	found := false
-	err := WithCluster(tx, authOpts, riakPort, func(cluster StorageCluster) error {
-		ro, err := FetchObjectValues(configFileKey, URLSigKeysBucket, cluster)
-		if err != nil {
-			return err
-		}
-		if len(ro) == 0 {
-			return nil // not found
-		}
-		if err := json.Unmarshal(ro[0].Value, &val); err != nil {
-			return errors.New("unmarshalling Riak response: " + err.Error())
-		}
-		found = true
-		return nil
-	})
-	if err != nil {
-		return val, false, err
+	if len(failures) > 0 {
+		return errors.New("successfully deleted Traffic Vault SSL keys for deleted dses [" + strings.Join(successes, ", ") + "], but failed to delete Traffic Vault SSL keys for [" + strings.Join(failures, ", ") + "]; see the error log for details")
 	}
-	return val, found, nil
+	return nil
 }
diff --git a/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak.go
new file mode 100644
index 0000000..fd0dc85
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak.go
@@ -0,0 +1,128 @@
+// Package riaksvc provides a TrafficVault implementation which uses Riak as the backend.
+package riaksvc
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+	"database/sql"
+	"encoding/json"
+	"errors"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/lib/go-tc/tovalidate"
+	"github.com/apache/trafficcontrol/lib/go-util"
+	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/trafficvault"
+
+	validation "github.com/go-ozzo/ozzo-validation"
+)
+
+const RiakBackendName = "riak"
+
+type Riak struct {
+	cfg Config
+}
+
+func (r *Riak) GetDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) (tc.DeliveryServiceSSLKeysV15, bool, error) {
+	return getDeliveryServiceSSLKeysObjV15(xmlID, version, tx, &r.cfg.AuthOptions, &r.cfg.Port)
+}
+
+func (r *Riak) PutDeliveryServiceSSLKeys(key tc.DeliveryServiceSSLKeys, tx *sql.Tx) error {
+	return putDeliveryServiceSSLKeysObj(key, tx, &r.cfg.AuthOptions, &r.cfg.Port)
+}
+
+func (r *Riak) DeleteDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) error {
+	return deleteDSSSLKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, xmlID, version)
+}
+
+func (r *Riak) DeleteOldDeliveryServiceSSLKeys(existingXMLIDs map[string]struct{}, cdnName string, tx *sql.Tx) error {
+	return deleteOldDeliveryServiceSSLKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, tc.CDNName(cdnName), existingXMLIDs)
+}
+
+func (r *Riak) GetCDNSSLKeys(cdnName string, tx *sql.Tx) ([]tc.CDNSSLKey, error) {
+	return getCDNSSLKeysObj(tx, &r.cfg.AuthOptions, &r.cfg.Port, cdnName)
+}
+
+func (r *Riak) GetDNSSECKeys(cdnName string, tx *sql.Tx) (tc.DNSSECKeysTrafficVault, bool, error) {
+	keys, exists, err := getDNSSECKeys(cdnName, tx, &r.cfg.AuthOptions, &r.cfg.Port)
+	return tc.DNSSECKeysTrafficVault(keys), exists, err
+}
+
+func (r *Riak) PutDNSSECKeys(cdnName string, keys tc.DNSSECKeysTrafficVault, tx *sql.Tx) error {
+	return putDNSSECKeys(tc.DNSSECKeysRiak(keys), cdnName, tx, &r.cfg.AuthOptions, &r.cfg.Port)
+}
+
+func (r *Riak) DeleteDNSSECKeys(cdnName string, tx *sql.Tx) error {
+	return deleteDNSSECKeys(cdnName, tx, &r.cfg.AuthOptions, &r.cfg.Port)
+}
+
+func (r *Riak) GetURLSigKeys(xmlID string, tx *sql.Tx) (tc.URLSigKeys, bool, error) {
+	return getURLSigKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, tc.DeliveryServiceName(xmlID))
+}
+
+func (r *Riak) PutURLSigKeys(xmlID string, keys tc.URLSigKeys, tx *sql.Tx) error {
+	return putURLSigKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, tc.DeliveryServiceName(xmlID), keys)
+}
+
+func (r *Riak) GetURISigningKeys(xmlID string, tx *sql.Tx) ([]byte, bool, error) {
+	return getURISigningKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, xmlID)
+}
+
+func (r *Riak) PutURISigningKeys(xmlID string, keysJson []byte, tx *sql.Tx) error {
+	return putURISigningKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, xmlID, keysJson)
+}
+
+func (r *Riak) DeleteURISigningKeys(xmlID string, tx *sql.Tx) error {
+	return deleteURISigningKeys(tx, &r.cfg.AuthOptions, &r.cfg.Port, xmlID)
+}
+
+func (r *Riak) Ping(tx *sql.Tx) (tc.TrafficVaultPingResponse, error) {
+	resp, err := ping(tx, &r.cfg.AuthOptions, &r.cfg.Port)
+	return tc.TrafficVaultPingResponse(resp), err
+}
+
+func (r *Riak) GetBucketKey(bucket string, key string, tx *sql.Tx) ([]byte, bool, error) {
+	return getBucketKey(tx, &r.cfg.AuthOptions, &r.cfg.Port, bucket, key)
+}
+
+func init() {
+	trafficvault.AddBackend(RiakBackendName, riakConfigLoad)
+}
+
+func riakConfigLoad(b json.RawMessage) (trafficvault.TrafficVault, error) {
+	riakCfg, err := unmarshalRiakConfig(b)
+	if err != nil {
+		return nil, err
+	}
+	if err := validateConfig(riakCfg); err != nil {
+		return nil, errors.New("validating Riak config: " + err.Error())
+	}
+	return &Riak{cfg: riakCfg}, nil
+}
+
+func validateConfig(cfg Config) error {
+	errs := tovalidate.ToErrors(validation.Errors{
+		"user":     validation.Validate(cfg.User, validation.Required),
+		"password": validation.Validate(cfg.Password, validation.Required),
+	})
+	if len(errs) == 0 {
+		return nil
+	}
+	return util.JoinErrs(errs)
+}
diff --git a/traffic_ops/traffic_ops_golang/riaksvc/riak_services.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services.go
similarity index 81%
rename from traffic_ops/traffic_ops_golang/riaksvc/riak_services.go
rename to traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services.go
index 937c955..532344a 100644
--- a/traffic_ops/traffic_ops_golang/riaksvc/riak_services.go
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services.go
@@ -25,7 +25,6 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"io/ioutil"
 	"reflect"
 	"runtime"
 	"sort"
@@ -40,11 +39,11 @@ import (
 )
 
 const (
-	// DefaultRiakPort is the port RIAK is listening on, if no port is configured.
-	DefaultRiakPort                    = uint(8087)
-	TimeOut                            = time.Second * 5
-	DefaultHealthCheckInterval         = time.Second * 5
-	DefaultMaxCommandExecutionAttempts = 5
+	// defaultRiakPort is the port RIAK is listening on, if no port is configured.
+	defaultRiakPort                    = uint(8087)
+	defaultTimeOut                     = time.Second * 5
+	defaultHealthCheckInterval         = time.Second * 5
+	defaultMaxCommandExecutionAttempts = 5
 )
 
 var (
@@ -58,6 +57,7 @@ var (
 type TOAuthOptions struct {
 	riak.AuthOptions
 	MaxTLSVersion *string
+	Port          uint `json:"port"`
 }
 
 // StorageCluster ...
@@ -109,21 +109,22 @@ func setMaxTLSVersion(riakConfig *TOAuthOptions) error {
 	return err
 }
 
-func GetRiakConfig(riakConfigFile string) (bool, *riak.AuthOptions, error) {
-	riakConfString, err := ioutil.ReadFile(riakConfigFile)
-	if err != nil {
-		return false, nil, fmt.Errorf("reading riak conf '%v': %v", riakConfigFile, err)
-	}
-
-	riakConfBytes := []byte(riakConfString)
+type Config struct {
+	riak.AuthOptions
+	Port uint
+}
 
+func unmarshalRiakConfig(riakConfBytes json.RawMessage) (Config, error) {
+	conf := Config{}
 	rconf := &TOAuthOptions{}
 	rconf.TlsConfig = &tls.Config{}
-	err = json.Unmarshal(riakConfBytes, &rconf)
+	err := json.Unmarshal(riakConfBytes, &rconf)
 	if err != nil {
-		return false, nil, fmt.Errorf("Unmarshaling riak conf '%v': %v", riakConfigFile, err)
+		return conf, err
+	}
+	if err := setMaxTLSVersion(rconf); err != nil {
+		return conf, err
 	}
-	setMaxTLSVersion(rconf)
 
 	type config struct {
 		Hci string `json:"HealthCheckInterval"`
@@ -141,17 +142,22 @@ func GetRiakConfig(riakConfigFile string) (bool, *riak.AuthOptions, error) {
 	}
 
 	if healthCheckInterval <= 0 {
-		healthCheckInterval = DefaultHealthCheckInterval
+		healthCheckInterval = defaultHealthCheckInterval
 		log.Infoln("HeathCheckInterval override")
 	}
 
 	log.Infoln("Riak health check interval set to:", healthCheckInterval)
 
-	return true, &rconf.AuthOptions, nil
+	conf.AuthOptions = rconf.AuthOptions
+	conf.Port = rconf.Port
+	if conf.Port == 0 {
+		conf.Port = defaultRiakPort
+	}
+	return conf, nil
 }
 
 // deletes an object from riak storage
-func DeleteObject(key string, bucket string, cluster StorageCluster) error {
+func deleteObject(key string, bucket string, cluster StorageCluster) error {
 	if cluster == nil {
 		return errors.New("ERROR: No valid cluster on which to execute a command")
 	}
@@ -160,7 +166,7 @@ func DeleteObject(key string, bucket string, cluster StorageCluster) error {
 	cmd, err := riak.NewDeleteValueCommandBuilder().
 		WithBucket(bucket).
 		WithKey(key).
-		WithTimeout(TimeOut).
+		WithTimeout(defaultTimeOut).
 		Build()
 	if err != nil {
 		return err
@@ -169,8 +175,8 @@ func DeleteObject(key string, bucket string, cluster StorageCluster) error {
 	return cluster.Execute(cmd)
 }
 
-// PingCluster pings the given Riak cluster, and returns nil on success, or any error
-func PingCluster(cluster StorageCluster) error {
+// pingCluster pings the given Riak cluster, and returns nil on success, or any error
+func pingCluster(cluster StorageCluster) error {
 	if cluster == nil {
 		return errors.New("ERROR: No valid cluster on which to execute a command")
 	}
@@ -196,7 +202,7 @@ func PingCluster(cluster StorageCluster) error {
 }
 
 // fetch an object from riak storage
-func FetchObjectValues(key string, bucket string, cluster StorageCluster) ([]*riak.Object, error) {
+func fetchObjectValues(key string, bucket string, cluster StorageCluster) ([]*riak.Object, error) {
 	if cluster == nil {
 		return nil, errors.New("ERROR: No valid cluster on which to execute a command")
 	}
@@ -204,7 +210,7 @@ func FetchObjectValues(key string, bucket string, cluster StorageCluster) ([]*ri
 	cmd, err := riak.NewFetchValueCommandBuilder().
 		WithBucket(bucket).
 		WithKey(key).
-		WithTimeout(TimeOut).
+		WithTimeout(defaultTimeOut).
 		Build()
 	if err != nil {
 		return nil, err
@@ -222,7 +228,7 @@ func FetchObjectValues(key string, bucket string, cluster StorageCluster) ([]*ri
 	return fvc.Response.Values, nil
 }
 
-func SaveObject(obj *riak.Object, bucket string, cluster StorageCluster) error {
+func saveObject(obj *riak.Object, bucket string, cluster StorageCluster) error {
 	if cluster == nil {
 		return errors.New("ERROR: No valid cluster on which to execute a command")
 	}
@@ -233,7 +239,7 @@ func SaveObject(obj *riak.Object, bucket string, cluster StorageCluster) error {
 	cmd, err := riak.NewStoreValueCommandBuilder().
 		WithBucket(bucket).
 		WithContent(obj).
-		WithTimeout(TimeOut).
+		WithTimeout(defaultTimeOut).
 		Build()
 	if err != nil {
 		return err
@@ -247,8 +253,8 @@ type ServerAddr struct {
 	Port string
 }
 
-// GetRiakServers returns the riak servers from the database. The riakPort may be nil, in which case the default port is returned.
-func GetRiakServers(tx *sql.Tx, riakPort *uint) ([]ServerAddr, error) {
+// getRiakServers returns the riak servers from the database. The riakPort may be nil, in which case the default port is returned.
+func getRiakServers(tx *sql.Tx, riakPort *uint) ([]ServerAddr, error) {
 	rows, err := tx.Query(`
 SELECT CONCAT(s.host_name, '.', s.domain_name) FROM server s
 JOIN type t ON s.type = t.id
@@ -261,7 +267,7 @@ WHERE t.name = 'RIAK' AND st.name = 'ONLINE'
 	defer rows.Close()
 	servers := []ServerAddr{}
 	if riakPort == nil {
-		riakPort = util.UIntPtr(DefaultRiakPort)
+		riakPort = util.UIntPtr(defaultRiakPort)
 	}
 	portStr := strconv.Itoa(int(*riakPort))
 	for rows.Next() {
@@ -275,7 +281,7 @@ WHERE t.name = 'RIAK' AND st.name = 'ONLINE'
 	return servers, nil
 }
 
-func GetRiakCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (*riak.Cluster, error) {
+func getRiakCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (*riak.Cluster, error) {
 	if authOptions == nil {
 		return nil, errors.New("ERROR: no riak auth information from riak.conf, cannot authenticate to any riak servers")
 	}
@@ -298,7 +304,7 @@ func GetRiakCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (*riak.
 	}
 	opts := &riak.ClusterOptions{
 		Nodes:             nodes,
-		ExecutionAttempts: DefaultMaxCommandExecutionAttempts,
+		ExecutionAttempts: defaultMaxCommandExecutionAttempts,
 	}
 	cluster, err := riak.NewCluster(opts)
 	if err != nil {
@@ -307,22 +313,22 @@ func GetRiakCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (*riak.
 	return cluster, err
 }
 
-func GetRiakStorageCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (StorageCluster, error) {
-	cluster, err := GetRiakCluster(servers, authOptions)
+func getRiakStorageCluster(servers []ServerAddr, authOptions *riak.AuthOptions) (StorageCluster, error) {
+	cluster, err := getRiakCluster(servers, authOptions)
 	if err != nil {
 		return nil, err
 	}
 	return RiakStorageCluster{Cluster: cluster}, nil
 }
 
-func GetPooledCluster(tx *sql.Tx, authOptions *riak.AuthOptions, riakPort *uint) (StorageCluster, error) {
+func getPooledCluster(tx *sql.Tx, authOptions *riak.AuthOptions, riakPort *uint) (StorageCluster, error) {
 	clusterMutex.Lock()
 	defer clusterMutex.Unlock()
 
 	tryLoad := false
 
 	// should we try to reload the cluster?
-	newservers, err := GetRiakServers(tx, riakPort)
+	newservers, err := getRiakServers(tx, riakPort)
 
 	if err == nil {
 		if 0 < len(newservers) {
@@ -344,7 +350,7 @@ func GetPooledCluster(tx *sql.Tx, authOptions *riak.AuthOptions, riakPort *uint)
 	}
 
 	if tryLoad {
-		newcluster, err := GetRiakCluster(newservers, authOptions)
+		newcluster, err := getRiakCluster(newservers, authOptions)
 		if err == nil {
 			if err := newcluster.Start(); err == nil {
 				log.Infof("New riak cluster started: %p\n", newcluster)
@@ -371,24 +377,24 @@ func GetPooledCluster(tx *sql.Tx, authOptions *riak.AuthOptions, riakPort *uint)
 	cluster := sharedCluster
 
 	if cluster == nil {
-		log.Errorln("GetPooledCluster failed, returning nil cluster")
-		return nil, errors.New("GetPooledCluster unable to return cluster")
+		log.Errorln("getPooledCluster failed, returning nil cluster")
+		return nil, errors.New("getPooledCluster unable to return cluster")
 	}
 
 	return RiakStorageCluster{Cluster: cluster}, nil
 }
 
-func WithCluster(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, f func(StorageCluster) error) error {
-	cluster, err := GetPooledCluster(tx, authOpts, riakPort)
+func withCluster(tx *sql.Tx, authOpts *riak.AuthOptions, riakPort *uint, f func(StorageCluster) error) error {
+	cluster, err := getPooledCluster(tx, authOpts, riakPort)
 	if err != nil {
 		return errors.New("getting riak pooled cluster: " + err.Error())
 	}
 	return f(cluster)
 }
 
-// Search searches Riak for the given query. Returns nil and a nil error if no object was found.
+// search searches Riak for the given query. Returns nil and a nil error if no object was found.
 // If fields is empty, all fields will be returned.
-func Search(cluster StorageCluster, index string, query string, filterQuery string, numRows int, fields []string) ([]*riak.SearchDoc, error) {
+func search(cluster StorageCluster, index string, query string, filterQuery string, numRows int, fields []string) ([]*riak.SearchDoc, error) {
 	riakCmd := riak.NewSearchCommandBuilder().
 		WithIndexName(index).
 		WithQuery(query).
diff --git a/traffic_ops/traffic_ops_golang/riaksvc/riak_services_test.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services_test.go
similarity index 85%
rename from traffic_ops/traffic_ops_golang/riaksvc/riak_services_test.go
rename to traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services_test.go
index 4651ca2..925b4a6 100644
--- a/traffic_ops/traffic_ops_golang/riaksvc/riak_services_test.go
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_services_test.go
@@ -64,22 +64,22 @@ func TestFetchObjectValues(t *testing.T) {
 		Running: true,
 	}
 
-	_, err := FetchObjectValues("myobject", "bucket", cluster)
+	_, err := fetchObjectValues("myobject", "bucket", cluster)
 	if err != nil {
 		t.Error("expected nil error got ", err)
 	}
 
-	_, err = FetchObjectValues("", "bucket", cluster)
+	_, err = fetchObjectValues("", "bucket", cluster)
 	if err == nil {
 		t.Error("expected an error because key is empty but got no error")
 	}
 
-	_, err = FetchObjectValues("myobject", "", cluster)
+	_, err = fetchObjectValues("myobject", "", cluster)
 	if err == nil {
 		t.Error("expected an error because the bucket name is empty but got no error")
 	}
 
-	_, err = FetchObjectValues("myobject", "mybucket", nil)
+	_, err = fetchObjectValues("myobject", "mybucket", nil)
 	if err == nil {
 		t.Error("expected an error because the cluster is nil but got no error")
 	}
@@ -92,22 +92,22 @@ func TestSaveObject(t *testing.T) {
 
 	obj := riak.Object{}
 
-	err := SaveObject(&obj, "bucket", cluster)
+	err := saveObject(&obj, "bucket", cluster)
 	if err != nil {
 		t.Error("expected nil error got ", err)
 	}
 
-	err = SaveObject(&obj, "", cluster)
+	err = saveObject(&obj, "", cluster)
 	if err == nil {
 		t.Error("expected an error due to empty bucket name but got a nil error")
 	}
 
-	err = SaveObject(nil, "bucket", cluster)
+	err = saveObject(nil, "bucket", cluster)
 	if err == nil {
 		t.Error("expected an error because the obj is nil but go no error", err)
 	}
 
-	err = SaveObject(&obj, "bucket", nil)
+	err = saveObject(&obj, "bucket", nil)
 	if err == nil {
 		t.Error("expected an error because the cluster is nil but go no error", err)
 	}
@@ -118,22 +118,22 @@ func TestDeleteObject(t *testing.T) {
 		Running: true,
 	}
 
-	err := DeleteObject("myobject", "bucket", cluster)
+	err := deleteObject("myobject", "bucket", cluster)
 	if err != nil {
 		t.Error("expected nil error got ", err)
 	}
 
-	err = DeleteObject("", "bucket", cluster)
+	err = deleteObject("", "bucket", cluster)
 	if err == nil {
 		t.Error("expected an empty key error but got nil error", err)
 	}
 
-	err = DeleteObject("myobject", "", cluster)
+	err = deleteObject("myobject", "", cluster)
 	if err == nil {
 		t.Error("expected an empty bucket error but got nil error", err)
 	}
 
-	err = DeleteObject("myobject", "bucket", nil)
+	err = deleteObject("myobject", "bucket", nil)
 	if err == nil {
 		t.Error("expected an nil cluster error but got nil error", err)
 	}
@@ -190,17 +190,17 @@ func TestGetRiakCluster(t *testing.T) {
 	defer tx.Commit()
 
 	mock.ExpectQuery("SELECT").WillReturnError(errors.New("foo"))
-	if _, err := GetRiakServers(tx, nil); err == nil {
+	if _, err := getRiakServers(tx, nil); err == nil {
 		t.Errorf("expected an error retrieving nil servers.")
 	}
 
 	mock.ExpectQuery("SELECT").WillReturnRows(rows1)
-	servers, err := GetRiakServers(tx, nil)
+	servers, err := getRiakServers(tx, nil)
 	if err != nil {
 		t.Errorf("expected to receive servers: %v", err)
 	}
 
-	if _, err := GetRiakCluster(servers, nil); err == nil {
+	if _, err := getRiakCluster(servers, nil); err == nil {
 		t.Errorf("expected an error due to nil RiakAuthoptions in the config but, go no error.")
 	}
 
@@ -210,14 +210,14 @@ func TestGetRiakCluster(t *testing.T) {
 		TlsConfig: &tls.Config{},
 	}
 
-	if _, err := GetRiakCluster(servers, &authOptions); err != nil {
+	if _, err := getRiakCluster(servers, &authOptions); err != nil {
 		t.Errorf("expected no errors, actual: %v", err)
 	}
 
 	rows2 := sqlmock.NewRows([]string{"s.host_name", "s.domain_name"})
 	mock.ExpectQuery("SELECT").WillReturnRows(rows2)
 
-	if _, err := GetPooledCluster(tx, &authOptions, nil); err == nil {
+	if _, err := getPooledCluster(tx, &authOptions, nil); err == nil {
 		t.Errorf("expected an error due to no available riak servers.")
 	}
 }
diff --git a/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_test.go b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_test.go
new file mode 100644
index 0000000..0a5c92e
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficvault/backends/riaksvc/riak_test.go
@@ -0,0 +1,93 @@
+package riaksvc
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+	"crypto/tls"
+	"testing"
+)
+
+const goodRiakConfig = `
+	   {
+	       "user": "riakuser",
+	       "password": "password",
+	       "port": 8087,
+	       "MaxTLSVersion": "1.1",
+	       "tlsConfig": {
+	           "insecureSkipVerify": true
+	       }
+	   }
+`
+
+func TestUnmarshalGoodRiakConfig(t *testing.T) {
+	if cfg, err := unmarshalRiakConfig([]byte(goodRiakConfig)); err != nil {
+		t.Errorf("unmarshalling good Riak config - expected: nil error, actual: %v", err)
+	} else {
+		if cfg.User != "riakuser" {
+			t.Errorf("unmarshalling good Riak config - expected user: riakuser, actual: %s", cfg.User)
+		}
+		if cfg.Password != "password" {
+			t.Errorf("unmarshalling good Riak config - expected password: password, actual: %s", cfg.Password)
+		}
+		if cfg.Port != 8087 {
+			t.Errorf("unmarshalling good Riak config - expected port: 8087, actual: %d", cfg.Port)
+		}
+		if cfg.TlsConfig == nil {
+			t.Fatal("unmarshalling good Riak config - expected TlsConfig: non-nil, actual: nil")
+		}
+		if cfg.TlsConfig.InsecureSkipVerify != true {
+			t.Errorf("unmarshalling good Riak config - expected TlsConfig.InsecureSkipVerify: true, actual: %t", cfg.TlsConfig.InsecureSkipVerify)
+		}
+		if cfg.TlsConfig.MaxVersion != tls.VersionTLS11 {
+			t.Errorf("unmarshalling good Riak config - expected TlsConfig.MaxVersion: %d, actual: %d", tls.VersionTLS11, cfg.TlsConfig.MaxVersion)
+		}
+	}
+}
+
+func TestUnmarshalBadRiakConfig(t *testing.T) {
+	type TestCase struct {
+		jsonStr string
+		reason  string
+	}
+	testCases := []TestCase{
+		{
+			jsonStr: `{"user": "foo"}`,
+			reason:  "missing password",
+		},
+		{
+			jsonStr: `{"password": "password"}`,
+			reason:  "missing user",
+		},
+		{
+			jsonStr: `{"user": "user", password": "password", "MaxTLSVersion": "1234"}`,
+			reason:  "invalid MaxTLSVersion",
+		},
+		{
+			jsonStr: `asdf`,
+			reason:  "invalid JSON",
+		},
+	}
+	for _, testCase := range testCases {
+		_, err := riakConfigLoad([]byte(testCase.jsonStr))
+		if err == nil {
+			t.Errorf("unmarshalling bad Riak config - expected error because %s, actual: no error", testCase.reason)
+		}
+	}
+}
diff --git a/traffic_ops/traffic_ops_golang/trafficvault/trafficvault.go b/traffic_ops/traffic_ops_golang/trafficvault/trafficvault.go
new file mode 100644
index 0000000..e788587
--- /dev/null
+++ b/traffic_ops/traffic_ops_golang/trafficvault/trafficvault.go
@@ -0,0 +1,112 @@
+// Package trafficvault provides the interfaces and types necessary to support various
+// Traffic Vault backend data stores.
+package trafficvault
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import (
+	"database/sql"
+	"encoding/json"
+	"fmt"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+)
+
+// TrafficVault defines the methods necessary for a struct to implement in order to
+// provide all the necessary functionality required of a Traffic Vault backend.
+type TrafficVault interface {
+	// GetDeliveryServiceSSLKeys retrieves the SSL keys of the given version for
+	// the delivery service identified by the given xmlID. If version is empty,
+	// the implementation should return the latest version.
+	GetDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) (tc.DeliveryServiceSSLKeysV15, bool, error)
+	// PutDeliveryServiceSSLKeys stores the given SSL keys for a delivery service.
+	PutDeliveryServiceSSLKeys(key tc.DeliveryServiceSSLKeys, tx *sql.Tx) error
+	// DeleteDeliveryServiceSSLKeys removes the SSL keys of the given version (or latest
+	// if version is empty) for the delivery service identified by the given xmlID.
+	DeleteDeliveryServiceSSLKeys(xmlID string, version string, tx *sql.Tx) error
+	// DeleteOldDeliveryServiceSSLKeys takes a set of existingXMLIDs as input and will remove
+	// all SSL keys for delivery services in the CDN identified by the given cdnName that
+	// do not contain an xmlID in the given set of existingXMLIDs. This method is called
+	// during a snapshot operation in order to delete SSL keys for delivery services that
+	// no longer exist.
+	DeleteOldDeliveryServiceSSLKeys(existingXMLIDs map[string]struct{}, cdnName string, tx *sql.Tx) error
+	// GetCDNSSLKeys retrieves all the SSL keys for delivery services in the CDN identified
+	// by the given cdnName.
+	GetCDNSSLKeys(cdnName string, tx *sql.Tx) ([]tc.CDNSSLKey, error)
+	// GetDNSSECKeys retrieves all the DNSSEC keys associated with the CDN identified by the
+	// given cdnName.
+	GetDNSSECKeys(cdnName string, tx *sql.Tx) (tc.DNSSECKeysTrafficVault, bool, error)
+	// PutDNSSECKeys stores all the DNSSEC keys for the CDN identified by the given cdnName.
+	PutDNSSECKeys(cdnName string, keys tc.DNSSECKeysTrafficVault, tx *sql.Tx) error
+	// DeleteDNSSECKeys removes all the DNSSEC keys for the CDN identified by the given cdnName.
+	DeleteDNSSECKeys(cdnName string, tx *sql.Tx) error
+	// GetURLSigKeys retrieves the URL sig keys for the delivery service identified by the
+	// given xmlID.
+	GetURLSigKeys(xmlID string, tx *sql.Tx) (tc.URLSigKeys, bool, error)
+	// PutURLSigKeys stores the given URL sig keys for the delivery service identified by
+	// the given xmlID.
+	PutURLSigKeys(xmlID string, keys tc.URLSigKeys, tx *sql.Tx) error
+	// GetURISigningKeys retrieves the URI signing keys (as raw JSON bytes) for the delivery
+	// service identified by the given xmlID.
+	GetURISigningKeys(xmlID string, tx *sql.Tx) ([]byte, bool, error)
+	// PutURISigningKeys stores the given URI signing keys (as raw JSON bytes) for the delivery
+	// service identified by the given xmlID.
+	PutURISigningKeys(xmlID string, keysJson []byte, tx *sql.Tx) error
+	// DeleteURISigningKeys removes the URI signing keys for the delivery service identified by
+	// the given xmlID.
+	DeleteURISigningKeys(xmlID string, tx *sql.Tx) error
+	// Ping simply checks the health of the Traffic Vault backend, returning a status and which
+	// server hostname the status was returned by.
+	Ping(tx *sql.Tx) (tc.TrafficVaultPingResponse, error)
+	// GetBucketKey returns the raw bytes identified by the given bucket and key. This may not
+	// apply to every Traffic Vault backend implementation.
+	GetBucketKey(bucket string, key string, tx *sql.Tx) ([]byte, bool, error)
+}
+
+var backends = make(map[string]LoadFunc)
+
+// A LoadFunc is a function that takes a json.RawMessage as input (the contents of
+// traffic_vault_config in cdn.conf) and returns a valid TrafficVault as output. Each
+// TrafficVault implementation should define its own LoadFunc which is responsible for
+// parsing the given configuration and returning a valid TrafficVault implementation that
+// may be used by request handlers.
+type LoadFunc func(json.RawMessage) (TrafficVault, error)
+
+// AddBackend should be called by each TrafficVault backend package's init() function in order
+// to register its name and LoadFunc. This name corresponds to the traffic_vault_backend option
+// in cdn.conf.
+func AddBackend(name string, loadConfig LoadFunc) {
+	backends[name] = loadConfig
+}
+
+// GetBackend is called with the contents of the traffic_vault_backend and traffic_vault_config
+// options in cdn.conf, respectively, in order to lookup and load the chosen Traffic Vault
+// backend to use.
+func GetBackend(name string, cfgJson json.RawMessage) (TrafficVault, error) {
+	loader, ok := backends[name]
+	if !ok {
+		return nil, fmt.Errorf("no support Traffic Vault backend named '%s' was found", name)
+	}
+	backend, err := loader(cfgJson)
+	if err != nil {
+		return nil, fmt.Errorf("failed to load backend '%s': %s", name, err.Error())
+	}
+	return backend, nil
+}
diff --git a/traffic_ops/traffic_ops_golang/urisigning/urisigning.go b/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
index f9a7bf4..5341d6f 100644
--- a/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
+++ b/traffic_ops/traffic_ops_golang/urisigning/urisigning.go
@@ -32,22 +32,9 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-rfc"
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/tenant"
-
-	"github.com/basho/riak-go-client"
-	"github.com/lestrrat/go-jwx/jwk"
 )
 
-// CDNURIKeysBucket is the namespace or bucket used for CDN URI signing keys.
-const CDNURIKeysBucket = "cdn_uri_sig_keys"
-
-// URISignerKeyset is the container for the CDN URI signing keys
-type URISignerKeyset struct {
-	RenewalKid *string               `json:"renewal_kid"`
-	Keys       []jwk.EssentialHeader `json:"keys"`
-}
-
 // endpoint handler for fetching uri signing keys from riak
 func GetURIsignkeysHandler(w http.ResponseWriter, r *http.Request) {
 	inf, userErr, sysErr, errCode := api.NewInfo(r, nil, nil)
@@ -57,8 +44,8 @@ func GetURIsignkeysHandler(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("The RIAK service is unavailable"), errors.New("getting Riak SSL keys by host name: riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("the Traffic Vault service is unavailable"), errors.New("getting Traffic Vault SSL keys by host name: Traffic Vault is not configured"))
 		return
 	}
 
@@ -68,24 +55,13 @@ func GetURIsignkeysHandler(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, errCode, userErr, sysErr)
 		return
 	}
-
-	cluster, err := riaksvc.GetPooledCluster(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	ro, _, err := inf.Vault.GetURISigningKeys(xmlID, inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("starting riak cluster: "+err.Error()))
-		return
-	}
-
-	ro, err := riaksvc.FetchObjectValues(xmlID, CDNURIKeysBucket, cluster)
-	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("fetching riak objects: "+err.Error()))
-		return
-	}
-	if len(ro) == 0 {
-		api.WriteRespRaw(w, r, URISignerKeyset{})
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting URI signing keys: "+err.Error()))
 		return
 	}
 	w.Header().Set("Content-Type", "application/json")
-	w.Write(ro[0].Value)
+	w.Write(ro)
 }
 
 // removeDeliveryServiceURIKeysHandler is the HTTP DELETE handler used to remove urisigning keys assigned to a delivery service.
@@ -97,8 +73,8 @@ func RemoveDeliveryServiceURIKeysHandler(w http.ResponseWriter, r *http.Request)
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("The RIAK service is unavailable"), errors.New("getting Riak SSL keys by host name: riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("rhe Traffic Vault service is unavailable"), errors.New("getting Traffic Vault SSL keys by host name: Traffic Vault is not configured"))
 		return
 	}
 
@@ -116,24 +92,18 @@ func RemoveDeliveryServiceURIKeysHandler(w http.ResponseWriter, r *http.Request)
 		return
 	}
 
-	cluster, err := riaksvc.GetPooledCluster(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
+	_, found, err := inf.Vault.GetURISigningKeys(xmlID, inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("starting riak cluster: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("removing URI signing keys: "+err.Error()))
 		return
 	}
 
-	ro, err := riaksvc.FetchObjectValues(xmlID, CDNURIKeysBucket, cluster)
-	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("fetching riak objects: "+err.Error()))
-		return
-	}
-
-	if len(ro) == 0 || ro[0].Value == nil {
+	if !found {
 		api.WriteRespAlert(w, r, tc.InfoLevel, "not deleted, no object found to delete")
 		return
 	}
-	if err := riaksvc.DeleteObject(xmlID, CDNURIKeysBucket, cluster); err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("deleting riak object: "+err.Error()))
+	if err := inf.Vault.DeleteURISigningKeys(xmlID, inf.Tx.Tx); err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("removing URI signing keys: "+err.Error()))
 		return
 	}
 	api.CreateChangeLogRawTx(api.ApiChange, "DS: "+xmlID+", ID: "+strconv.Itoa(dsID)+", ACTION: Removed URI signing keys", inf.User, inf.Tx.Tx)
@@ -150,8 +120,8 @@ func SaveDeliveryServiceURIKeysHandler(w http.ResponseWriter, r *http.Request) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("The RIAK service is unavailable"), errors.New("getting Riak SSL keys by host name: riak is not configured"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusServiceUnavailable, errors.New("the Traffic Vault service is unavailable"), errors.New("getting Traffic Vault SSL keys by host name: Traffic Vault is not configured"))
 		return
 	}
 
@@ -174,7 +144,7 @@ func SaveDeliveryServiceURIKeysHandler(w http.ResponseWriter, r *http.Request) {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, errors.New("failed to read body"), errors.New("failed to read body: "+err.Error()))
 		return
 	}
-	keySet := map[string]URISignerKeyset{}
+	keySet := map[string]tc.URISignerKeyset{}
 	if err := json.Unmarshal(data, &keySet); err != nil {
 		api.HandleErr(w, r, inf.Tx.Tx, http.StatusBadRequest, errors.New("malformed JSON"), nil)
 		return
@@ -184,22 +154,8 @@ func SaveDeliveryServiceURIKeysHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	cluster, err := riaksvc.GetPooledCluster(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort)
-	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("starting riak cluster: "+err.Error()))
-		return
-	}
-
-	obj := &riak.Object{
-		ContentType:     "text/json",
-		Charset:         "utf-8",
-		ContentEncoding: "utf-8",
-		Key:             xmlID,
-		Value:           []byte(data),
-	}
-
-	if err = riaksvc.SaveObject(obj, CDNURIKeysBucket, cluster); err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("saving riak object: "+err.Error()))
+	if err := inf.Vault.PutURISigningKeys(xmlID, data, inf.Tx.Tx); err != nil {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("saving URI signing keys: "+err.Error()))
 		return
 	}
 	api.CreateChangeLogRawTx(api.ApiChange, "DS: "+xmlID+", ID: "+strconv.Itoa(dsID)+", ACTION: Stored URI signing keys to a delivery service", inf.User, inf.Tx.Tx)
@@ -220,7 +176,7 @@ func getDSIDFromName(tx *sql.Tx, xmlID string) (int, bool, error) {
 }
 
 // validateURIKeyset validates URISigingKeyset json.
-func validateURIKeyset(msg map[string]URISignerKeyset) error {
+func validateURIKeyset(msg map[string]tc.URISignerKeyset) error {
 	var renewalKidFound int
 	var renewalKidMatched = false
 
diff --git a/traffic_ops/traffic_ops_golang/urisigning/urisigning_test.go b/traffic_ops/traffic_ops_golang/urisigning/urisigning_test.go
index 983b591..8b31f3d 100644
--- a/traffic_ops/traffic_ops_golang/urisigning/urisigning_test.go
+++ b/traffic_ops/traffic_ops_golang/urisigning/urisigning_test.go
@@ -22,6 +22,8 @@ package urisigning
 import (
 	"encoding/json"
 	"testing"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
 )
 
 const (
@@ -127,7 +129,7 @@ const (
 )
 
 func TestValidateURIKeyset(t *testing.T) {
-	var keyset map[string]URISignerKeyset
+	var keyset map[string]tc.URISignerKeyset
 
 	// unmarshal a good URISignerKeyset
 	if err := json.Unmarshal([]byte(goodKeyset), &keyset); err != nil {
diff --git a/traffic_ops/traffic_ops_golang/vault/bucket.go b/traffic_ops/traffic_ops_golang/vault/bucket.go
index 4f925d7..79217b2 100644
--- a/traffic_ops/traffic_ops_golang/vault/bucket.go
+++ b/traffic_ops/traffic_ops_golang/vault/bucket.go
@@ -22,11 +22,11 @@ package vault
 import (
 	"encoding/json"
 	"errors"
+	"net/http"
+
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/lib/go-util"
 	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/api"
-	"github.com/apache/trafficcontrol/traffic_ops/traffic_ops_golang/riaksvc"
-	"net/http"
 )
 
 func GetBucketKeyDeprecated(w http.ResponseWriter, r *http.Request) {
@@ -45,14 +45,14 @@ func getBucketKey(w http.ResponseWriter, r *http.Request, a tc.Alerts) {
 	}
 	defer inf.Close()
 
-	if inf.Config.RiakEnabled == false {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("riak.GetBucketKey: Riak is not configured!"))
+	if !inf.Config.TrafficVaultEnabled {
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, userErr, errors.New("getting bucket key: Traffic Vault is not configured"))
 		return
 	}
 
-	val, ok, err := riaksvc.GetBucketKey(inf.Tx.Tx, inf.Config.RiakAuthOptions, inf.Config.RiakPort, inf.Params["bucket"], inf.Params["key"])
+	val, ok, err := inf.Vault.GetBucketKey(inf.Params["bucket"], inf.Params["key"], inf.Tx.Tx)
 	if err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting bucket key from Riak: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("getting bucket key from Traffic Vault: "+err.Error()))
 		return
 	}
 	if !ok {
@@ -62,7 +62,7 @@ func getBucketKey(w http.ResponseWriter, r *http.Request, a tc.Alerts) {
 
 	valObj := map[string]interface{}{}
 	if err := json.Unmarshal(val, &valObj); err != nil {
-		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("GetBucketKey bucket '"+inf.Params["bucket"]+"' key '"+inf.Params["key"]+"' Riak returned invalid JSON: "+err.Error()))
+		api.HandleErr(w, r, inf.Tx.Tx, http.StatusInternalServerError, nil, errors.New("GetBucketKey bucket '"+inf.Params["bucket"]+"' key '"+inf.Params["key"]+"' Traffic Vault returned invalid JSON: "+err.Error()))
 		return
 	}