github.com/argoproj/argo-cd@v1.8.7/util/dex/config.go (about) 1 package dex 2 3 import ( 4 "fmt" 5 6 "github.com/ghodss/yaml" 7 8 "github.com/argoproj/argo-cd/common" 9 "github.com/argoproj/argo-cd/util/settings" 10 ) 11 12 func GenerateDexConfigYAML(settings *settings.ArgoCDSettings) ([]byte, error) { 13 if !settings.IsDexConfigured() { 14 return nil, nil 15 } 16 redirectURL, err := settings.RedirectURL() 17 if err != nil { 18 return nil, fmt.Errorf("failed to infer redirect url from config: %v", err) 19 } 20 var dexCfg map[string]interface{} 21 err = yaml.Unmarshal([]byte(settings.DexConfig), &dexCfg) 22 if err != nil { 23 return nil, fmt.Errorf("failed to unmarshal dex.config from configmap: %v", err) 24 } 25 dexCfg["issuer"] = settings.IssuerURL() 26 dexCfg["storage"] = map[string]interface{}{ 27 "type": "memory", 28 } 29 dexCfg["web"] = map[string]interface{}{ 30 "http": "0.0.0.0:5556", 31 } 32 dexCfg["grpc"] = map[string]interface{}{ 33 "addr": "0.0.0.0:5557", 34 } 35 dexCfg["telemetry"] = map[string]interface{}{ 36 "http": "0.0.0.0:5558", 37 } 38 dexCfg["oauth2"] = map[string]interface{}{ 39 "skipApprovalScreen": true, 40 } 41 42 argoCDStaticClient := map[string]interface{}{ 43 "id": common.ArgoCDClientAppID, 44 "name": common.ArgoCDClientAppName, 45 "secret": settings.DexOAuth2ClientSecret(), 46 "redirectURIs": []string{ 47 redirectURL, 48 }, 49 } 50 argoCDCLIStaticClient := map[string]interface{}{ 51 "id": common.ArgoCDCLIClientAppID, 52 "name": common.ArgoCDCLIClientAppName, 53 "public": true, 54 "redirectURIs": []string{ 55 "http://localhost", 56 "http://localhost:8085/auth/callback", 57 }, 58 } 59 60 staticClients, ok := dexCfg["staticClients"].([]interface{}) 61 if ok { 62 dexCfg["staticClients"] = append([]interface{}{argoCDStaticClient, argoCDCLIStaticClient}, staticClients...) 63 } else { 64 dexCfg["staticClients"] = []interface{}{argoCDStaticClient, argoCDCLIStaticClient} 65 } 66 67 dexRedirectURL, err := settings.DexRedirectURL() 68 if err != nil { 69 return nil, err 70 } 71 connectors, ok := dexCfg["connectors"].([]interface{}) 72 if !ok { 73 return nil, fmt.Errorf("malformed Dex configuration found") 74 } 75 for i, connectorIf := range connectors { 76 connector, ok := connectorIf.(map[string]interface{}) 77 if !ok { 78 return nil, fmt.Errorf("malformed Dex configuration found") 79 } 80 connectorType := connector["type"].(string) 81 if !needsRedirectURI(connectorType) { 82 continue 83 } 84 connectorCfg, ok := connector["config"].(map[string]interface{}) 85 if !ok { 86 return nil, fmt.Errorf("malformed Dex configuration found") 87 } 88 connectorCfg["redirectURI"] = dexRedirectURL 89 connector["config"] = connectorCfg 90 connectors[i] = connector 91 } 92 dexCfg["connectors"] = connectors 93 dexCfg = replaceMapSecrets(dexCfg, settings.Secrets) 94 return yaml.Marshal(dexCfg) 95 } 96 97 // replaceMapSecrets takes a json object and recursively looks for any secret key references in the 98 // object and replaces the value with the secret value 99 func replaceMapSecrets(obj map[string]interface{}, secretValues map[string]string) map[string]interface{} { 100 newObj := make(map[string]interface{}) 101 for k, v := range obj { 102 switch val := v.(type) { 103 case map[string]interface{}: 104 newObj[k] = replaceMapSecrets(val, secretValues) 105 case []interface{}: 106 newObj[k] = replaceListSecrets(val, secretValues) 107 case string: 108 newObj[k] = settings.ReplaceStringSecret(val, secretValues) 109 default: 110 newObj[k] = val 111 } 112 } 113 return newObj 114 } 115 116 func replaceListSecrets(obj []interface{}, secretValues map[string]string) []interface{} { 117 newObj := make([]interface{}, len(obj)) 118 for i, v := range obj { 119 switch val := v.(type) { 120 case map[string]interface{}: 121 newObj[i] = replaceMapSecrets(val, secretValues) 122 case []interface{}: 123 newObj[i] = replaceListSecrets(val, secretValues) 124 case string: 125 newObj[i] = settings.ReplaceStringSecret(val, secretValues) 126 default: 127 newObj[i] = val 128 } 129 } 130 return newObj 131 } 132 133 // needsRedirectURI returns whether or not the given connector type needs a redirectURI 134 // Update this list as necessary, as new connectors are added 135 // https://github.com/dexidp/dex/tree/master/Documentation/connectors 136 func needsRedirectURI(connectorType string) bool { 137 switch connectorType { 138 case "oidc", "saml", "microsoft", "linkedin", "gitlab", "github", "bitbucket-cloud", "openshift": 139 return true 140 } 141 return false 142 }