15000: Add Workbench configs.
[arvados.git] / lib / config / export.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package config
6
7 import (
8         "encoding/json"
9         "errors"
10         "fmt"
11         "io"
12         "strings"
13
14         "git.curoverse.com/arvados.git/sdk/go/arvados"
15 )
16
17 // ExportJSON writes a JSON object with the safe (non-secret) portions
18 // of the cluster config to w.
19 func ExportJSON(w io.Writer, cluster *arvados.Cluster) error {
20         buf, err := json.Marshal(cluster)
21         if err != nil {
22                 return err
23         }
24         var m map[string]interface{}
25         err = json.Unmarshal(buf, &m)
26         if err != nil {
27                 return err
28         }
29         err = redactUnsafe(m, "", "")
30         if err != nil {
31                 return err
32         }
33         return json.NewEncoder(w).Encode(m)
34 }
35
36 // whitelist classifies configs as safe/unsafe to reveal to
37 // unauthenticated clients.
38 //
39 // Every config entry must either be listed explicitly here along with
40 // all of its parent keys (e.g., "API" + "API.RequestTimeout"), or
41 // have an ancestor listed as false (e.g.,
42 // "PostgreSQL.Connection.password" has an ancestor
43 // "PostgreSQL.Connection" with a false value). Otherwise, it is a bug
44 // which should be caught by tests.
45 //
46 // Example: API.RequestTimeout is safe because whitelist["API"] == and
47 // whitelist["API.RequestTimeout"] == true.
48 //
49 // Example: PostgreSQL.Connection.password is not safe because
50 // whitelist["PostgreSQL.Connection"] == false.
51 //
52 // Example: PostgreSQL.BadKey would cause an error because
53 // whitelist["PostgreSQL"] isn't false, and neither
54 // whitelist["PostgreSQL.BadKey"] nor whitelist["PostgreSQL.*"]
55 // exists.
56 var whitelist = map[string]bool{
57         // | sort -t'"' -k2,2
58         "API":                                                    true,
59         "API.AsyncPermissionsUpdateInterval":                     true,
60         "API.DisabledAPIs":                                       true,
61         "API.MaxIndexDatabaseRead":                               true,
62         "API.MaxItemsPerResponse":                                true,
63         "API.MaxRequestAmplification":                            true,
64         "API.MaxRequestSize":                                     true,
65         "API.RailsSessionSecretToken":                            false,
66         "API.RequestTimeout":                                     true,
67         "AuditLogs":                                              true,
68         "AuditLogs.MaxAge":                                       true,
69         "AuditLogs.MaxDeleteBatch":                               true,
70         "AuditLogs.UnloggedAttributes":                           true,
71         "Collections":                                            true,
72         "Collections.BlobSigning":                                true,
73         "Collections.BlobSigningKey":                             false,
74         "Collections.BlobSigningTTL":                             true,
75         "Collections.CollectionVersioning":                       true,
76         "Collections.DefaultReplication":                         true,
77         "Collections.DefaultTrashLifetime":                       true,
78         "Collections.PreserveVersionIfIdle":                      true,
79         "Collections.TrashSweepInterval":                         true,
80         "Containers":                                             true,
81         "Containers.CloudVMs":                                    true,
82         "Containers.CloudVMs.BootProbeCommand":                   true,
83         "Containers.CloudVMs.Driver":                             true,
84         "Containers.CloudVMs.DriverParameters":                   false,
85         "Containers.CloudVMs.Enable":                             true,
86         "Containers.CloudVMs.ImageID":                            true,
87         "Containers.CloudVMs.MaxCloudOpsPerSecond":               true,
88         "Containers.CloudVMs.MaxProbesPerSecond":                 true,
89         "Containers.CloudVMs.PollInterval":                       true,
90         "Containers.CloudVMs.ProbeInterval":                      true,
91         "Containers.CloudVMs.ResourceTags":                       true,
92         "Containers.CloudVMs.ResourceTags.*":                     true,
93         "Containers.CloudVMs.SSHPort":                            true,
94         "Containers.CloudVMs.SyncInterval":                       true,
95         "Containers.CloudVMs.TagKeyPrefix":                       true,
96         "Containers.CloudVMs.TimeoutBooting":                     true,
97         "Containers.CloudVMs.TimeoutIdle":                        true,
98         "Containers.CloudVMs.TimeoutProbe":                       true,
99         "Containers.CloudVMs.TimeoutShutdown":                    true,
100         "Containers.CloudVMs.TimeoutSignal":                      true,
101         "Containers.CloudVMs.TimeoutTERM":                        true,
102         "Containers.DefaultKeepCacheRAM":                         true,
103         "Containers.DispatchPrivateKey":                          true,
104         "Containers.JobsAPI":                                     true,
105         "Containers.JobsAPI.CrunchJobUser":                       true,
106         "Containers.JobsAPI.CrunchJobWrapper":                    true,
107         "Containers.JobsAPI.CrunchRefreshTrigger":                true,
108         "Containers.JobsAPI.DefaultDockerImage":                  true,
109         "Containers.JobsAPI.Enable":                              true,
110         "Containers.JobsAPI.GitInternalDir":                      true,
111         "Containers.JobsAPI.ReuseJobIfOutputsDiffer":             true,
112         "Containers.Logging":                                     true,
113         "Containers.Logging.LimitLogBytesPerJob":                 true,
114         "Containers.Logging.LogBytesPerEvent":                    true,
115         "Containers.Logging.LogPartialLineThrottlePeriod":        true,
116         "Containers.Logging.LogSecondsBetweenEvents":             true,
117         "Containers.Logging.LogThrottleBytes":                    true,
118         "Containers.Logging.LogThrottleLines":                    true,
119         "Containers.Logging.LogThrottlePeriod":                   true,
120         "Containers.Logging.LogUpdatePeriod":                     true,
121         "Containers.Logging.LogUpdateSize":                       true,
122         "Containers.Logging.MaxAge":                              true,
123         "Containers.LogReuseDecisions":                           true,
124         "Containers.MaxComputeVMs":                               true,
125         "Containers.MaxDispatchAttempts":                         true,
126         "Containers.MaxRetryAttempts":                            true,
127         "Containers.SLURM":                                       true,
128         "Containers.SLURM.Managed":                               true,
129         "Containers.SLURM.Managed.AssignNodeHostname":            true,
130         "Containers.SLURM.Managed.ComputeNodeDomain":             false,
131         "Containers.SLURM.Managed.ComputeNodeNameservers":        false,
132         "Containers.SLURM.Managed.DNSServerConfDir":              true,
133         "Containers.SLURM.Managed.DNSServerConfTemplate":         true,
134         "Containers.SLURM.Managed.DNSServerReloadCommand":        false,
135         "Containers.SLURM.Managed.DNSServerUpdateCommand":        false,
136         "Containers.StaleLockTimeout":                            true,
137         "Containers.SupportedDockerImageFormats":                 true,
138         "Containers.UsePreemptibleInstances":                     true,
139         "Git":                                                    true,
140         "Git.Repositories":                                       true,
141         "InstanceTypes":                                          true,
142         "InstanceTypes.*":                                        true,
143         "InstanceTypes.*.*":                                      true,
144         "Login":                                                  true,
145         "Login.ProviderAppID":                                    false,
146         "Login.ProviderAppSecret":                                false,
147         "Mail":                                                   true,
148         "Mail.EmailFrom":                                         true,
149         "Mail.IssueReporterEmailFrom":                            true,
150         "Mail.IssueReporterEmailTo":                              true,
151         "Mail.MailchimpAPIKey":                                   false,
152         "Mail.MailchimpListID":                                   false,
153         "Mail.SendUserSetupNotificationEmail":                    true,
154         "Mail.SupportEmailAddress":                               true,
155         "ManagementToken":                                        false,
156         "PostgreSQL":                                             true,
157         "PostgreSQL.Connection":                                  false,
158         "PostgreSQL.ConnectionPool":                              true,
159         "RemoteClusters":                                         true,
160         "RemoteClusters.*":                                       true,
161         "RemoteClusters.*.ActivateUsers":                         true,
162         "RemoteClusters.*.Host":                                  true,
163         "RemoteClusters.*.Insecure":                              true,
164         "RemoteClusters.*.Proxy":                                 true,
165         "RemoteClusters.*.Scheme":                                true,
166         "Services":                                               true,
167         "Services.*":                                             true,
168         "Services.*.ExternalURL":                                 true,
169         "Services.*.InternalURLs":                                true,
170         "Services.*.InternalURLs.*":                              true,
171         "Services.*.InternalURLs.*.*":                            true,
172         "SystemLogs":                                             true,
173         "SystemLogs.Format":                                      true,
174         "SystemLogs.LogLevel":                                    true,
175         "SystemLogs.MaxRequestLogParamsSize":                     true,
176         "SystemRootToken":                                        false,
177         "TLS":                                                    true,
178         "TLS.Certificate":                                        true,
179         "TLS.Insecure":                                           true,
180         "TLS.Key":                                                false,
181         "Users":                                                  true,
182         "Users.AdminNotifierEmailFrom":                           true,
183         "Users.AutoAdminFirstUser":                               false,
184         "Users.AutoAdminUserWithEmail":                           false,
185         "Users.AutoSetupNewUsers":                                true,
186         "Users.AutoSetupNewUsersWithRepository":                  true,
187         "Users.AutoSetupNewUsersWithVmUUID":                      true,
188         "Users.AutoSetupUsernameBlacklist":                       false,
189         "Users.EmailSubjectPrefix":                               true,
190         "Users.NewInactiveUserNotificationRecipients":            false,
191         "Users.NewUserNotificationRecipients":                    false,
192         "Users.NewUsersAreActive":                                true,
193         "Users.UserNotifierEmailFrom":                            true,
194         "Users.UserProfileNotificationAddress":                   true,
195         "Workbench":                                              true,
196         "Workbench.ActivationContactLink":                        true,
197         "Workbench.APIClientConnectTimeout":                      true,
198         "Workbench.APIClientReceiveTimeout":                      true,
199         "Workbench.APIResponseCompression":                       true,
200         "Workbench.ApplicationMimetypesWithViewIcon":             true,
201         "Workbench.ApplicationMimetypesWithViewIcon.*":           true,
202         "Workbench.ArvadosDocsite":                               true,
203         "Workbench.ArvadosPublicDataDocURL":                      true,
204         "Workbench.EnableGettingStartedPopup":                    true,
205         "Workbench.EnablePublicProjectsPage":                     true,
206         "Workbench.FileViewersConfigURL":                         true,
207         "Workbench.LogViewerMaxBytes":                            true,
208         "Workbench.MultiSiteSearch":                              true,
209         "Workbench.Repositories":                                 true,
210         "Workbench.RepositoryCache":                              true,
211         "Workbench.RunningJobLogRecordsToFetch":                  true,
212         "Workbench.SecretKeyBase":                                false,
213         "Workbench.SecretToken":                                  false,
214         "Workbench.ShowRecentCollectionsOnDashboard":             true,
215         "Workbench.ShowUserAgreementInline":                      true,
216         "Workbench.ShowUserNotifications":                        true,
217         "Workbench.SiteName":                                     true,
218         "Workbench.Theme":                                        true,
219         "Workbench.UserProfileFormFields":                        true,
220         "Workbench.UserProfileFormFields.*":                      true,
221         "Workbench.UserProfileFormFields.*.Type":                 true,
222         "Workbench.UserProfileFormFields.*.FormFieldTitle":       true,
223         "Workbench.UserProfileFormFields.*.FormFieldDescription": true,
224         "Workbench.UserProfileFormFields.*.Required":             true,
225         "Workbench.UserProfileFormMessage":                       true,
226         "Workbench.VocabularyURL":                                true,
227 }
228
229 func redactUnsafe(m map[string]interface{}, mPrefix, lookupPrefix string) error {
230         var errs []string
231         for k, v := range m {
232                 lookupKey := k
233                 safe, ok := whitelist[lookupPrefix+k]
234                 if !ok {
235                         lookupKey = "*"
236                         safe, ok = whitelist[lookupPrefix+"*"]
237                 }
238                 if !ok {
239                         errs = append(errs, fmt.Sprintf("config bug: key %q not in whitelist map", lookupPrefix+k))
240                         continue
241                 }
242                 if !safe {
243                         delete(m, k)
244                         continue
245                 }
246                 if v, ok := v.(map[string]interface{}); ok {
247                         err := redactUnsafe(v, mPrefix+k+".", lookupPrefix+lookupKey+".")
248                         if err != nil {
249                                 errs = append(errs, err.Error())
250                         }
251                 }
252         }
253         if len(errs) > 0 {
254                 return errors.New(strings.Join(errs, "\n"))
255         }
256         return nil
257 }