-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgcp_function.go
157 lines (142 loc) · 3.88 KB
/
gcp_function.go
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
package ksm_google_scim
import (
"context"
"errors"
"fmt"
"github.com/GoogleCloudPlatform/functions-framework-go/functions"
"github.com/cloudevents/sdk-go/v2/event"
ksm "github.com/keeper-security/secrets-manager-go/core"
"io"
"keepersecurity.com/ksm-scim/scim"
"log"
"net/http"
"net/url"
"os"
"strings"
)
func init() {
// Register an HTTP function with the Functions Framework
functions.HTTP("GcpScimSyncHttp", gcpScimSyncHttp)
functions.CloudEvent("GcpScimSyncPubSub", gcpScimSyncPubSub)
}
const ksmConfigName = "KSM_CONFIG_BASE64"
const ksmRecordUid = "KSM_RECORD_UID"
func runScimSync() (syncStat *scim.SyncStat, err error) {
var configBase64 = os.Getenv(ksmConfigName)
if len(configBase64) == 0 {
err = errors.New(fmt.Sprintf("Environment variable \"%s\" is not set", ksmConfigName))
log.Println(err)
return
}
var config = ksm.NewMemoryKeyValueStorage(configBase64)
var sm = ksm.NewSecretsManager(&ksm.ClientOptions{
Config: config,
})
var filter []string
var recordUid = os.Getenv(ksmRecordUid)
if len(recordUid) > 0 {
filter = append(filter, recordUid)
}
var records []*ksm.Record
if records, err = sm.GetSecrets(filter); err != nil {
log.Println(err)
return
}
var scimRecord *ksm.Record
for _, r := range records {
if r.Type() != "login" {
continue
}
var webUrl = r.GetFieldValueByType("url")
if len(webUrl) == 0 {
continue
}
var uri *url.URL
var er1 error
if uri, er1 = url.Parse(webUrl); er1 != nil {
continue
}
if !strings.HasPrefix(uri.Path, "/api/rest/scim/v2/") {
continue
}
var files = r.FindFiles("credentials.json")
if len(files) == 0 {
continue
}
scimRecord = r
break
}
if scimRecord == nil {
err = errors.New("SCIM record was not found. Make sure the record is valid and shared to KSM application")
log.Println(err)
return
}
var ka *scim.ScimEndpointParameters
var gcp *scim.GoogleEndpointParameters
if ka, gcp, err = scim.LoadScimParametersFromRecord(scimRecord); err != nil {
log.Println(err)
return
}
var googleEndpoint = scim.NewGoogleEndpoint(gcp.Credentials, gcp.AdminAccount, gcp.ScimGroups)
var sync = scim.NewScimSync(googleEndpoint, ka.Url, ka.Token)
sync.SetVerbose(ka.Verbose)
sync.SetDestructive(ka.Destructive)
if syncStat, err = sync.Sync(); err == nil {
printStatistics(os.Stdout, syncStat)
}
return
}
func printStatistics(w io.Writer, syncStat *scim.SyncStat) {
if syncStat != nil {
if len(syncStat.SuccessGroups) > 0 {
_, _ = fmt.Fprintf(w, "Group Success:\n")
for _, txt := range syncStat.SuccessGroups {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
if len(syncStat.FailedGroups) > 0 {
_, _ = fmt.Fprintf(w, "Group Failure:\n")
for _, txt := range syncStat.FailedGroups {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
if len(syncStat.SuccessUsers) > 0 {
_, _ = fmt.Fprintf(w, "User Success:\n")
for _, txt := range syncStat.SuccessUsers {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
if len(syncStat.FailedUsers) > 0 {
_, _ = fmt.Fprintf(w, "User Failure:\n")
for _, txt := range syncStat.FailedUsers {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
if len(syncStat.SuccessMembership) > 0 {
_, _ = fmt.Fprintf(w, "Membership Success:\n")
for _, txt := range syncStat.SuccessMembership {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
if len(syncStat.FailedMembership) > 0 {
_, _ = fmt.Fprintf(w, "Membership Failure:\n")
for _, txt := range syncStat.FailedMembership {
_, _ = fmt.Fprintf(w, "\t%s\n", txt)
}
}
}
}
// Function gcpScimSync is an HTTP handler
func gcpScimSyncHttp(w http.ResponseWriter, r *http.Request) {
var syncStat, err = runScimSync()
if err == nil {
printStatistics(w, syncStat)
} else {
log.Fatal(err)
}
}
// helloPubSub consumes a CloudEvent message and extracts the Pub/Sub message.
func gcpScimSyncPubSub(_ context.Context, _ event.Event) (err error) {
_, err = runScimSync()
return
}