-
Notifications
You must be signed in to change notification settings - Fork 0
/
acl-audit-report.Rmd
154 lines (118 loc) · 4.86 KB
/
acl-audit-report.Rmd
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
---
title: "Content Access/Permissions Audit Report"
output:
html_document:
theme: lumen
rmd_output_metadata:
rsc_output_files:
- "acl-detail-audit.csv"
---
`r if(Sys.getenv('CONNECT_SERVER') == '') { "<h4>ERROR: You must set the CONNECT_SERVER environment variable</h4>\n" }`
`r if(Sys.getenv('CONNECT_API_KEY') == '') { "<h4>ERROR: You must set the CONNECT_API_KEY environment variable</h4>\n" }`
`r if(Sys.getenv('CONNECT_API_KEY') == '' || Sys.getenv('CONNECT_SERVER') == '') { knitr::knit_exit() }`
**Generate a detailed list of all content items that have been shared with specific users or groups on RStudio Connect.**
This report assumes you have already created Pins for the result of an administrator call to `/v1/content` (content enumeration), `/v1/users`, and `/v1/groups`.
## Get the Content List Pin
```{r echo=FALSE}
#
# ** BEFORE EXECUTING **
# - REPLACE PIN NAME
# - REPLACE SERVER URL
#
# Register RStudio Connect
library(pins)
board_register("rsconnect", server = "YOUR-SERVER-URL")
# Retrieve Pin
content <- pin_get(name = "YOUR-PIN/content-info", board = "rsconnect")
```
Create a summary table of the number of content items under each access type.
- **`acl`** Access Control List - Specific users or groups
- **`logged_in`** All users - login required
- **`all`** Anyone - no login required
```{r access-summary, echo=FALSE, message=FALSE, warning=FALSE}
library(dplyr)
library(gt)
df <- content %>%
select(guid, name, title, access_type, created_time, last_deployed_time, content_url, dashboard_url)
df %>% count(access_type, sort = TRUE) %>%
gt() %>%
tab_header(
title = "Sharing Settings",
subtitle = "RStudio Connect Server Content Audit"
) %>%
cols_label(
access_type = "Access Type",
n = "Count"
)
```
```{r include=FALSE}
# Filter content list by 'acl' access_type
acl_only <- df %>%
filter(access_type == 'acl')
```
## Permissions API
```{r include=FALSE}
library(httr)
# Function for calling the content `/permissions` API endpoint
get_permissions <- function(guid) {
permissions <- GET(paste0(Sys.getenv("CONNECT_SERVER"),"__api__/v1/content/",guid,"/permissions"),
add_headers(Authorization = paste("Key", Sys.getenv("CONNECT_API_KEY"))))
tidyr::unnest_wider(tibble::tibble(dat = content(permissions)), dat)
}
# Get permissions for all ACL-type content items
# Content that is accessible only by the publisher-owner (no additional users or groups) will return no records
acl_info <- lapply(acl_only$guid, get_permissions)
acl_tibble <- tidyr::unnest(tibble::tibble(dat = acl_info), dat)
# Calculate the number of content items accessible by the publisher-owner plus additional users or groups
acl_distinct <- acl_tibble %>%
select(content_guid) %>%
n_distinct()
```
#### Content items accessible only by the publisher-owner (no additional users or groups): `r nrow(acl_only) - acl_distinct`
#### Content items accessible by a list of specific users or groups: `r acl_distinct`
For each content item shared with additional specific users and groups, report the user/group and list whether they have viewer or collaborator access:
```{r echo=FALSE}
#
# REPLACE PIN NAMES BEFORE EXECUTING
# - user_list
# - group_list
#
library(reactable)
# Get the user info Pin
user_list <- pin_get(name = "YOUR-PIN/user-info", board = "rsconnect")
# Get the group info Pin
group_list <- pin_get(name = "YOUR-PIN/group-info", board = "rsconnect")
# Add user and group names to the permission info
acl_detail <- acl_tibble %>%
left_join(user_list, by=c("principal_guid" = "guid")) %>%
left_join(group_list, by=c("principal_guid" = "guid")) %>%
select(id, content_guid, principal_guid, principal_type, role, username, email, user_role, locked, name) %>%
rename(group_name = name)
audit_table <- acl_detail %>%
left_join(content, by=c("content_guid" = "guid")) %>%
rename(content_name = name,
content_title = title,
share_username = username,
share_email = email,
share_type = principal_type,
share_role = role,
share_group = group_name) %>%
select(content_guid, content_title, dashboard_url, share_role, share_type, share_username, share_group)
reactable(audit_table, searchable = TRUE, highlight = TRUE, columns = list(
content_guid = colDef(name = "GUID"),
content_title = colDef(name = "Title"),
dashboard_url = colDef(name = "Content URL", cell = function(value) {
htmltools::tags$a(href = value, target = "_blank", "Link")
}),
share_role = colDef(name = "Access Type"),
share_type = colDef(name = "User/Group"),
share_username = colDef(name = "User Name"),
share_group = colDef(name = "Group Name")
))
```
### Download the full report contents
```{r include=FALSE}
# Write the audit_table response out to a CSV file for download
write.csv(audit_table, "acl-detail-audit.csv", row.names=FALSE)
```
- Report: [acl-detail-audit.csv](acl-detail-audit.csv)