github.com/pluralsh/plural-cli@v0.9.5/pkg/bundle/oidc.go (about) 1 package bundle 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/AlecAivazis/survey/v2" 8 9 "github.com/pluralsh/plural-cli/pkg/api" 10 "github.com/pluralsh/plural-cli/pkg/manifest" 11 "github.com/pluralsh/plural-cli/pkg/utils" 12 ) 13 14 var oidcConfirmed bool 15 16 func ConfigureOidc(repo string, client api.Client, recipe *api.Recipe, ctx map[string]interface{}, confirm *bool) error { 17 if recipe.OidcSettings == nil { 18 return nil 19 } 20 21 ok, err := confirmOidc(confirm) 22 if err != nil { 23 return err 24 } 25 26 if !ok { 27 return nil 28 } 29 30 settings := recipe.OidcSettings 31 redirectUris, err := formatRedirectUris(settings, ctx) 32 if err != nil { 33 return err 34 } 35 36 inst, err := client.GetInstallation(repo) 37 if err != nil { 38 return api.GetErrorResponse(err, "GetInstallation") 39 } 40 41 me, err := client.Me() 42 if err != nil { 43 return api.GetErrorResponse(err, "Me") 44 } 45 46 oidcSettings := &api.OidcProviderAttributes{ 47 RedirectUris: redirectUris, 48 AuthMethod: settings.AuthMethod, 49 Bindings: []api.Binding{ 50 {UserId: me.Id}, 51 }, 52 } 53 mergeOidcAttributes(inst, oidcSettings) 54 err = client.OIDCProvider(inst.Id, oidcSettings) 55 return api.GetErrorResponse(err, "OIDCProvider") 56 } 57 58 func SetupOIDC(repo string, client api.Client, redirectUris []string, authMethod string) error { 59 inst, err := client.GetInstallation(repo) 60 if err != nil { 61 return api.GetErrorResponse(err, "GetInstallation") 62 } 63 64 me, err := client.Me() 65 if err != nil { 66 return api.GetErrorResponse(err, "Me") 67 } 68 69 oidcSettings := &api.OidcProviderAttributes{ 70 RedirectUris: redirectUris, 71 AuthMethod: authMethod, 72 Bindings: []api.Binding{ 73 {UserId: me.Id}, 74 }, 75 } 76 mergeOidcAttributes(inst, oidcSettings) 77 err = client.OIDCProvider(inst.Id, oidcSettings) 78 return api.GetErrorResponse(err, "OIDCProvider") 79 } 80 81 func mergeOidcAttributes(inst *api.Installation, attributes *api.OidcProviderAttributes) { 82 if inst.OIDCProvider == nil { 83 return 84 } 85 86 provider := inst.OIDCProvider 87 attributes.RedirectUris = utils.Dedupe(append(attributes.RedirectUris, provider.RedirectUris...)) 88 bindings := attributes.Bindings 89 for _, val := range provider.Bindings { 90 // attributes is only pre-populated with the current user right now 91 if val.User != nil && val.User.Id != attributes.Bindings[0].UserId { 92 bindings = append(bindings, api.Binding{UserId: val.User.Id}) 93 } else if val.Group != nil { 94 bindings = append(bindings, api.Binding{GroupId: val.Group.Id}) 95 } 96 } 97 attributes.Bindings = bindings 98 } 99 100 func formatRedirectUris(settings *api.OIDCSettings, ctx map[string]interface{}) ([]string, error) { 101 res := make([]string, 0) 102 domain := "" 103 104 if settings.DomainKey != "" { 105 d, ok := ctx[settings.DomainKey] 106 if !ok { 107 return res, fmt.Errorf("No domain setting for %s in context", settings.DomainKey) 108 } 109 110 domain = d.(string) 111 } 112 113 proj, err := manifest.FetchProject() 114 if err != nil { 115 return res, err 116 } 117 118 fmtUri := func(uri string) string { 119 if domain != "" { 120 uri = strings.ReplaceAll(uri, "{domain}", domain) 121 } 122 123 if settings.Subdomain { 124 uri = strings.ReplaceAll(uri, "{subdomain}", proj.Network.Subdomain) 125 } 126 127 return uri 128 } 129 130 if settings.UriFormat != "" { 131 return []string{fmtUri(settings.UriFormat)}, err 132 } 133 134 for _, uri := range settings.UriFormats { 135 res = append(res, fmtUri(uri)) 136 } 137 138 return res, nil 139 } 140 141 func confirmOidc(confirm *bool) (bool, error) { 142 if confirm != nil && *confirm { 143 oidcConfirmed = true 144 } 145 146 if oidcConfirmed { 147 return true, nil 148 } 149 150 value, ok := utils.GetEnvBoolValue("PLURAL_CONFIRM_OIDC") 151 if ok { 152 confirm = &value 153 } else { 154 if err := survey.AskOne(&survey.Confirm{ 155 Message: "Enable plural OIDC", 156 Default: true, 157 }, confirm, survey.WithValidator(survey.Required)); err != nil { 158 return false, err 159 } 160 } 161 162 return *confirm, nil 163 }