in lib/oathclients/clients.go [139:209]
func SyncState(httpClient *http.Client, hydraAdminURL string, clients map[string]*pb.Client, secrets map[string]string) (*pb.ClientState, error) {
state := &pb.ClientState{
Add: make(map[string]*pb.Client),
Update: make(map[string]*pb.Client),
UpdateDiff: make(map[string]string),
Remove: make(map[string]*pb.Client),
Unchanged: make(map[string]*pb.Client),
NoSecret: make(map[string]*pb.Client),
SecretMismatch: []string{},
}
cs, err := hydra.ListClients(httpClient, hydraAdminURL)
if err != nil {
return nil, err
}
// Populate existing Hydra clients by ClientID. As the logic handles
// these clients, remove them from this map. Remaining items no longer
// exist in the Federated Access component, so delete the from Hydra.
removable := make(map[string]*hydraapi.Client)
for _, c := range cs {
removable[c.ClientID] = c
}
// Add clients to hydra.
for n, cli := range clients {
c := &pb.Client{}
proto.Merge(c, cli)
c.Ui = nil
sec, ok := secrets[c.ClientId]
if !ok {
glog.Errorf("sync hydra clients: client %q has no secret, and will not be included in Hydra client list.", n)
state.NoSecret[n] = c
continue
}
hc, ok := removable[c.ClientId]
if !ok {
// Does not exist in hydra, so create.
state.Add[n] = c
continue
}
// Update an existing client if it has changed.
fhc, hsec := fromHydraClient(hc)
if cmp.Equal(fhc, c, protocmp.Transform(), cmpopts.EquateEmpty()) && hsec == sec {
state.Unchanged[n] = c
} else {
state.Update[n] = c
if sec != hsec {
// Add the name of the client only, do not reveal the secrets in the state.
state.SecretMismatch = append(state.SecretMismatch, n)
}
// Take the diff again without revealing the secrets.
state.UpdateDiff[n] = cmp.Diff(fhc, c, protocmp.Transform(), cmpopts.EquateEmpty())
}
// Whether updated or unchanged above, remove it from the `removable` list to avoid removing the hydra client below.
delete(removable, hc.ClientID)
}
// Remove remaining existing hydra clients on the `removable` list.
for _, hc := range removable {
c, _ := fromHydraClient(hc)
state.Remove[hc.Name] = c
}
sort.Strings(state.SecretMismatch)
msg := fmt.Sprintf("hydra clients status: add %d, update %d, remove %d, unchanged %d, no_secret %d", len(state.Add), len(state.Update), len(state.Remove), len(state.Unchanged), len(state.NoSecret))
state.Status = httputils.NewStatus(codes.OK, msg).Proto()
return state, nil
}