R/keys.R

#' Encryption keys in Key Vault
#'
#' This class represents the collection of encryption keys stored in a vault. It provides methods for managing keys, including creating, importing and deleting keys, and doing backups and restores. For operations with a specific key, see [key].
#'
#' @docType class
#'
#' @section Methods:
#' This class provides the following methods:
#' ```
#' create(name, type=c("RSA", "EC"), hardware=FALSE,
#'        ec_curve=NULL, rsa_key_size=NULL, key_ops=NULL,
#'        attributes=vault_object_attrs(), ...)
#' import(name, key, hardware=FALSE,
#'        attributes=vault_object_attrs(), ...)
#' get(name)
#' delete(name, confirm=TRUE)
#' list(include_managed=FALSE)
#' backup(name)
#' restore(backup)
#' ```
#' @section Arguments:
#' - `name`: The name of the key.
#' - `type`: For `create`, the type of key to create: RSA or elliptic curve (EC). Note that for keys backing a certificate, only RSA is allowed.
#' - `hardware`: For `create`, Whether to use a hardware key or software key. The former requires a premium key vault.
#' - `ec_curve`: For an EC key, the type of elliptic curve.
#' - `rsa_key_size`: For an RSA key, the key size, either 2048, 3072 or 4096.
#' - `key_ops`: A character vector of operations that the key supports. The possible operations are "encrypt", "decrypt", "sign", "verify", "wrapkey" and "unwrapkey". See [key] for more information.
#' - `attributes`: Optional attributes for the key, such as the expiry date and activation date. A convenient way to provide this is via the [vault_object_attrs] helper function.
#' - `key`: For `import`, the key to import. This can be the name of a PEM file, a JSON web key (JWK) string, or a key object generated by the openssl package. See the examples below.
#' - `hardware`: For `import`, whether to import this key as a hardware key (HSM). Only supported for a premium key vault.
#' - `...`: For `create` and `import`, other named arguments which will be treated as tags.
#' - `include_managed`: For `list`, whether to include keys that were created by Key Vault to support a managed certificate.
#' - `backup`: For `restore`, a string representing the backup blob for a key.
#'
#' @section Value:
#' For `get`, `create` and `import`, an object of class `stored_key`, representing the key itself. This has methods for carrying out the operations given by the `key_ops` argument.
#'
#' For `list`, a vector of key names.
#'
#' For `backup`, a string representing the backup blob for a key. If the key has multiple versions, the blob will contain all versions.
#'
#' @seealso
#' [key], [vault_object_attrs]
#'
#' [Azure Key Vault documentation](https://docs.microsoft.com/en-us/azure/key-vault/),
#' [Azure Key Vault API reference](https://docs.microsoft.com/en-us/rest/api/keyvault)
#'
#' @examples
#' \dontrun{
#'
#' vault <- key_vault("mykeyvault")
#'
#' vault$keys$create("mynewkey")
#' vault$keys$create("myRSAkey", type="RSA", rsa_key_size=4096)
#' vault$keys$create("myECkey", type="EC", ec_curve="P-384")
#'
#' vault$keys$list()
#' vault$keys$get("mynewkey")
#'
#' # specifying an expiry date
#' today <- Sys.date()
#' vault$keys$create("mynewkey", attributes=vault_object_attrs(expiry_date=today+365))
#'
#' # setting management tags
#' vault$keys$create("mynewkey", tag1="a value", othertag="another value")
#'
#' # importing a key from a PEM file
#' vault$keys$import("importedkey1", "myprivatekey.pem")
#'
#' # importing a key generated by OpenSSL
#' vault$keys$import("importedkey2", openssl::rsa_keygen())
#'
#' # importing a JWK (which is a JSON string)
#' key <- openssl::read_key("myprivatekey.pem")
#' jwk <- jose::write_jwk(key)
#' vault$keys$import("importedkey3", jwk)
#'
#' # backup and restore a key
#' bak <- vault$keys$backup("mynewkey")
#' vault$keys$delete("mynewkey", confirm=FALSE)
#' vault$keys$restore(bak)
#'
#' }
#' @name keys
#' @rdname keys
NULL

vault_keys <- R6::R6Class("vault_keys",

public=list(

    token=NULL,
    url=NULL,

    initialize=function(token, url)
    {
        self$token <- token
        self$url <- url
    },

    create=function(name, type=c("RSA", "EC"), hardware=FALSE, ec_curve=NULL, rsa_key_size=NULL, key_ops=NULL,
                    attributes=vault_object_attrs(), ...)
    {
        type <- match.arg(type)
        key <- switch(type,
            "RSA"=list(kty=type, key_size=rsa_key_size),
            "EC"=list(kty=type, crv=ec_curve))

        if(hardware)
            key$kty <- paste0(key$kty, "-HSM")

        body <- c(key, list(attributes=attributes, key_ops=key_ops, tags=list(...)))

        op <- construct_path(name, "create")
        self$do_operation(op, body=body, encode="json", http_verb="POST")
        self$get(name)
    },

    get=function(name)
    {
        stored_key$new(self$token, self$url, name, NULL, self$do_operation(name))
    },

    delete=function(name, confirm=TRUE)
    {
        if(delete_confirmed(confirm, name, "key"))
            invisible(self$do_operation(name, http_verb="DELETE"))
    },

    list=function(include_managed=FALSE)
    {
        objs <- get_vault_paged_list(self$do_operation(), self$token)
        lst <- lapply(objs, function(props)
            if(!include_managed && isTRUE(props$managed)) NULL else basename(props$kid))
        unlist(compact(lst))
    },

    backup=function(name)
    {
        op <- construct_path(name, "backup")
        self$do_operation(op, http_verb="POST")$value
    },

    restore=function(backup)
    {
        stopifnot(is.character(backup))
        op <- construct_path(name, "restore")
        self$do_operation(op, body=list(value=backup), encode="json", http_verb="POST")
    },

    import=function(name, key, hardware=FALSE, attributes=vault_object_attrs(), ...)
    {
        # support importing keys from openssl package, or as json text, or as a PEM file
        if(is.character(key) && file.exists(key))
            key <- openssl::read_key(key)

        if(inherits(key, "key"))
            key <- jose::write_jwk(key)

        if(is.character(key) && jsonlite::validate(key))
            key <- jsonlite::fromJSON(key)

        body <- list(key=key, hsm=hardware, attributes=attributes, tags=list(...))
        self$do_operation(name, body=body, encode="json", http_verb="PUT")
        self$get(name)
    },

    do_operation=function(op="", ..., options=list())
    {
        url <- self$url
        url$path <- construct_path("keys", op)
        url$query <- options
        call_vault_url(self$token, url, ...)
    },

    print=function(...)
    {
        url <- self$url
        url$path <- "keys"
        cat("<key vault endpoint '", httr::build_url(url), "'>\n", sep="")
        invisible(self)
    }
))
cloudyr/AzureKeyVault documentation built on Sept. 19, 2021, 8:49 a.m.