/
vault_client_auth_github.R
166 lines (154 loc) · 5.97 KB
/
vault_client_auth_github.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
##' Interact with vault's GitHub authentication backend. For more
##' details, please see the vault documentation at
##' https://developer.hashicorp.com/vault/docs/auth/github
##'
##' @title Vault GitHub Authentication Configuration
##' @name vault_client_auth_github
##'
##' @examples
##' server <- vaultr::vault_test_server(if_disabled = message)
##' token <- Sys.getenv("VAULT_TEST_AUTH_GITHUB_TOKEN")
##' if (!is.null(server) && nzchar(token)) {
##' client <- server$client()
##'
##' client$auth$enable("github")
##' # To enable login for members of the organisation "example":
##' client$auth$github$configure(organization = "example")
##' # To map members of the "robots" team *within* that organisation
##' # to the "defaut" policy:
##' client$auth$github$write("development", "default")
##'
##' # Once configured like this, if we have a PAT for a member of
##' # the "development" team saved as an environment variable
##' # "VAULT_AUTH_GITHUB_TOKEN" then doing
##' #
##' # vaultr::vault_client(addr = ..., login = "github")
##' #
##' # will contact GitHub to verify the user token and vault will
##' # then issue a client token
##'
##' # cleanup
##' server$kill()
##' }
vault_client_auth_github <- R6::R6Class(
"vault_client_auth_github",
inherit = vault_client_object,
cloneable = FALSE,
private = list(
api_client = NULL,
mount = NULL
),
public = list(
##' @description Create a `vault_client_github` object. Not typically
##' called by users.
##'
##' @param api_client A [vaultr::vault_api_client] object
##'
##' @param mount Mount point for the backend
initialize = function(api_client, mount) {
super$initialize("Interact and configure vault's github support")
assert_scalar_character(mount)
private$mount <- sub("^/", "", mount)
private$api_client <- api_client
},
##' @description Set up a `vault_client_auth_github` object at a
##' custom mount. For example, suppose you mounted the `github`
##' authentication backend at `/github-myorg` you might use `gh
##' <- vault$auth$github2$custom_mount("/github-myorg")` - this
##' pattern is repeated for other secret and authentication
##' backends.
##'
##' @param mount String, indicating the path that the engine is
##' mounted at.
custom_mount = function(mount) {
vault_client_auth_github$new(private$api_client, mount)
},
##' @description Configures the connection parameters for
##' GitHub-based authentication.
##'
##' @param organization The organization users must be part of
##' (note American spelling).
##'
##' @param base_url The API endpoint to
##' use. Useful if you are running GitHub Enterprise or an
##' API-compatible authentication server.
##'
##' @param ttl Duration after which authentication will be expired
##'
##' @param max_ttl Maximum duration after which authentication will
##' be expired
configure = function(organization, base_url = NULL, ttl = NULL,
max_ttl = NULL) {
path <- sprintf("/auth/%s/config", private$mount)
assert_scalar_character(organization)
body <- list(organization = organization,
base_url = base_url,
ttl = ttl,
max_ttl = max_ttl)
private$api_client$POST(path, body = drop_null(body))
invisible(TRUE)
},
##' @description Reads the connection parameters for GitHub-based
##' authentication.
configuration = function() {
private$api_client$GET(sprintf("/auth/%s/config", private$mount))$data
},
##' @description Write a mapping between a GitHub team or user and
##' a set of vault policies.
##'
##' @param team_name String, with the GitHub team name
##'
##' @param policies A character vector of vault policies that this
##' user or team will have for vault access if they match this
##' team or user.
##'
##' @param user Scalar logical - if `TRUE`, then `team_name` is
##' interpreted as a *user* instead.
write = function(team_name, policies, user = FALSE) {
type <- if (assert_scalar_logical(user)) "users" else "teams"
assert_scalar_character(team_name)
path <- sprintf("/auth/%s/map/%s/%s", private$mount, type, team_name)
assert_character(policies)
body <- list(value = paste(policies, collapse = ","))
private$api_client$POST(path, body = body)
invisible(NULL)
},
##' @description Write a mapping between a GitHub team or user and
##' a set of vault policies.
##'
##' @param team_name String, with the GitHub team name
##'
##' @param user Scalar logical - if `TRUE`, then `team_name` is
##' interpreted as a *user* instead.
read = function(team_name, user = FALSE) {
type <- if (assert_scalar_logical(user)) "users" else "teams"
assert_scalar_character(team_name)
path <- sprintf("/auth/%s/map/%s/%s", private$mount, type, team_name)
private$api_client$GET(path)$data
},
##' @description Log into the vault using GitHub authentication.
##' Normally you would not call this directly but instead use
##' `$login` with `method = "github"` and proving the `token`
##' argument. This function returns a vault token but does not
##' set it as the client token.
##'
##' @param token A GitHub token to authenticate with.
login = function(token = NULL) {
path <- sprintf("/auth/%s/login", private$mount)
body <- list(token = vault_auth_github_token(token))
res <- private$api_client$POST(path, body = body,
allow_missing_token = TRUE)
res$auth
}
))
vault_auth_github_token <- function(token) {
if (is.null(token)) {
token <- Sys_getenv("VAULT_AUTH_GITHUB_TOKEN", NULL)
}
if (is.null(token)) {
stop(
"GitHub token was not found: perhaps set 'VAULT_AUTH_GITHUB_TOKEN'")
}
assert_scalar_character(token)
token
}