Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
111 lines (97 sloc)
3.71 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #' Select the default backend and default keyring | |
| #' | |
| #' The default backend is selected | |
| #' 1. based on the `keyring_backend` option. See [base::options()]. | |
| #' This can be set to a character string, and then the | |
| #' *backend_*`string` class is used to create the default backend. | |
| #' 1. If this is not set, then the `R_KEYRING_BACKEND` environment variable | |
| #' is checked. | |
| #' 1. If this is not set, either, then the backend is selected | |
| #' automatically, based on the OS: | |
| #' 1. On Windows, the Windows Credential Store (`"wincred"`) is used. | |
| #' 1. On macOS, Keychain services are selected (`"macos"`). | |
| #' 1. Linux uses the Secret Service API (`"secret_service"`), | |
| #' and it also checks that the service is available. It is typically | |
| #' only available on systems with a GUI. | |
| #' 1. On other operating systems, secrets are stored in environment | |
| #' variables (`"env"`). | |
| #' | |
| #' Most backends support multiple keyrings. For these the keyring is | |
| #' selected from: | |
| #' 1. the supplied `keyring` argument (if not `NULL`), or | |
| #' 1. the `keyring_keyring` option. | |
| #' - You can change this by using `options(keyring_keyring = "NEWVALUE")` | |
| #' 1. If this is not set, the `R_KEYRING_KEYRING` environment variable. | |
| #' - Change this value with `Sys.setenv(R_KEYRING_KEYRING = "NEWVALUE")`, | |
| #' either in your script or in your `.Renviron` file. | |
| #' See [base::Startup] for information about using `.Renviron` | |
| #' 1. Finally, if neither of these are set, the OS default keyring is used. | |
| #' - Usually the keyring is automatically unlocked when the user logs in. | |
| #' | |
| #' @param keyring Character string, the name of the keyring to use, | |
| #' or `NULL` for the default keyring. | |
| #' @return The backend object itself. | |
| #' | |
| #' | |
| #' @seealso [backend_env], [backend_file], [backend_macos], | |
| #' [backend_secret_service], [backend_wincred] | |
| #' | |
| #' @export | |
| #' @name backends | |
| default_backend <- function(keyring = NULL) { | |
| assert_that(is_string_or_null(keyring)) | |
| backend <- getOption("keyring_backend", "") | |
| if (identical(backend, "")) backend <- default_backend_env_or_auto() | |
| ## Is it just a backend name? | |
| if (is_string(backend)) backend <- backend_factory(backend) | |
| ## At this point 'backend' is a backend R6 class | |
| ## Check if a specific keyring is requested | |
| if (is.null(keyring)) { | |
| keyring <- getOption( | |
| "keyring_keyring", | |
| Sys.getenv("R_KEYRING_KEYRING", "") | |
| ) | |
| } | |
| if (! is.null(keyring) && nzchar(keyring)) { | |
| backend$new(keyring = keyring) | |
| } else { | |
| backend$new() | |
| } | |
| } | |
| default_backend_env_or_auto <- function() { | |
| backend <- Sys.getenv("R_KEYRING_BACKEND", "") | |
| if (identical(backend, "")) backend <- default_backend_auto() | |
| backend | |
| } | |
| default_backend_auto <- function() { | |
| sysname <- tolower(Sys.info()[["sysname"]]) | |
| if (sysname == "windows" && "wincred" %in% names(known_backends)) { | |
| backend_wincred | |
| } else if (sysname == "darwin" && "macos" %in% names(known_backends)) { | |
| backend_macos | |
| } else if (sysname == "linux" && "secret_service" %in% names(known_backends) && | |
| backend_secret_service$new()$is_available()) { | |
| backend_secret_service | |
| } else { | |
| if (getOption("keyring_warn_for_env_fallback", TRUE)) { | |
| warning("Selecting ", sQuote("env"), " backend. ", | |
| "Secrets are stored in environment variables") | |
| } | |
| backend_env | |
| } | |
| } | |
| backend_factory <- function(name) { | |
| assert_that(is_string(name)) | |
| if (!name %in% names(known_backends)) { | |
| stop("Unknown backend: ", sQuote(name)) | |
| } | |
| class_name <- paste0("backend_", name) | |
| get(class_name, envir = parent.frame()) | |
| } | |
| known_backends <- list( | |
| "wincred" = backend_wincred, | |
| "macos" = backend_macos, | |
| "secret_service" = backend_secret_service, | |
| "env" = backend_env, | |
| "file" = backend_file | |
| ) |